@oxyhq/services 8.7.0 → 10.0.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 (63) hide show
  1. package/lib/commonjs/ui/components/OxyProvider.js +2 -2
  2. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  3. package/lib/commonjs/ui/components/SignInModal.js +14 -3
  4. package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
  5. package/lib/commonjs/ui/context/OxyContext.js +30 -18
  6. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  7. package/lib/commonjs/ui/hooks/useWebSSO.js +7 -8
  8. package/lib/commonjs/ui/hooks/useWebSSO.js.map +1 -1
  9. package/lib/commonjs/ui/screens/OxyAuthScreen.js +14 -3
  10. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  11. package/lib/commonjs/utils/silentGuardKey.js +54 -0
  12. package/lib/commonjs/utils/silentGuardKey.js.map +1 -0
  13. package/lib/module/ui/components/OxyProvider.js +2 -2
  14. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  15. package/lib/module/ui/components/SignInModal.js +14 -3
  16. package/lib/module/ui/components/SignInModal.js.map +1 -1
  17. package/lib/module/ui/context/OxyContext.js +30 -18
  18. package/lib/module/ui/context/OxyContext.js.map +1 -1
  19. package/lib/module/ui/hooks/useWebSSO.js +7 -8
  20. package/lib/module/ui/hooks/useWebSSO.js.map +1 -1
  21. package/lib/module/ui/screens/OxyAuthScreen.js +14 -3
  22. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  23. package/lib/module/utils/silentGuardKey.js +49 -0
  24. package/lib/module/utils/silentGuardKey.js.map +1 -0
  25. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
  26. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +12 -8
  27. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  28. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  29. package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts.map +1 -1
  30. package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  31. package/lib/typescript/commonjs/ui/types/navigation.d.ts +8 -6
  32. package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
  33. package/lib/typescript/commonjs/utils/silentGuardKey.d.ts +31 -0
  34. package/lib/typescript/commonjs/utils/silentGuardKey.d.ts.map +1 -0
  35. package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
  36. package/lib/typescript/module/ui/context/OxyContext.d.ts +12 -8
  37. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  38. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  39. package/lib/typescript/module/ui/hooks/useWebSSO.d.ts.map +1 -1
  40. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  41. package/lib/typescript/module/ui/types/navigation.d.ts +8 -6
  42. package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
  43. package/lib/typescript/module/utils/silentGuardKey.d.ts +31 -0
  44. package/lib/typescript/module/utils/silentGuardKey.d.ts.map +1 -0
  45. package/package.json +2 -2
  46. package/src/ui/components/OxyProvider.tsx +2 -2
  47. package/src/ui/components/SignInModal.tsx +14 -3
  48. package/src/ui/context/OxyContext.tsx +42 -29
  49. package/src/ui/hooks/useWebSSO.ts +7 -8
  50. package/src/ui/screens/OxyAuthScreen.tsx +14 -3
  51. package/src/ui/types/navigation.ts +8 -6
  52. package/src/utils/__tests__/silentGuardKey.test.ts +82 -0
  53. package/src/utils/silentGuardKey.ts +46 -0
  54. package/lib/commonjs/ui/utils/appName.js +0 -62
  55. package/lib/commonjs/ui/utils/appName.js.map +0 -1
  56. package/lib/module/ui/utils/appName.js +0 -59
  57. package/lib/module/ui/utils/appName.js.map +0 -1
  58. package/lib/typescript/commonjs/ui/utils/appName.d.ts +0 -22
  59. package/lib/typescript/commonjs/ui/utils/appName.d.ts.map +0 -1
  60. package/lib/typescript/module/ui/utils/appName.d.ts +0 -22
  61. package/lib/typescript/module/ui/utils/appName.d.ts.map +0 -1
  62. package/src/ui/utils/__tests__/appName.test.ts +0 -52
  63. package/src/ui/utils/appName.ts +0 -62
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Shared, pure helpers for building the `origin|baseURL` signature used as the
3
+ * module-level run-once guard key for cold-boot silent-SSO probes
4
+ * (`silentColdBootKey` in `OxyContext`, `ssoSignature` in `useWebSSO`).
5
+ *
6
+ * NATIVE SAFETY (the bug this fixes): React Native aliases a global `window`
7
+ * (it points at the JS global object), so `typeof window !== 'undefined'` is
8
+ * `true` on native — but `window.location` is `undefined`. Reading
9
+ * `window.location.origin` after only a `typeof window` check therefore throws
10
+ * `TypeError: Cannot read property 'origin' of undefined` on native. Because
11
+ * the key is built UNCONDITIONALLY at the top of the cold-boot path (before its
12
+ * try/catch), that throw escaped session restore entirely and broke
13
+ * cross-session restore on native. Both prior copies of the guard had the same
14
+ * insufficient `typeof window` check and were prone to drift, so the read is
15
+ * consolidated here behind a guard that also verifies `window.location`.
16
+ */
17
+ /**
18
+ * Read `window.location.origin` safely on every platform.
19
+ *
20
+ * Returns the browser origin on web, and the sentinel `'no-origin'` anywhere
21
+ * `window.location` is absent (React Native, SSR/Node). Never throws.
22
+ */
23
+ export declare function safeWindowOrigin(): string;
24
+ /**
25
+ * Build the stable `origin|baseURL` signature for the silent-SSO run-once
26
+ * guard. Two providers pointed at the same API from the same origin share one
27
+ * attempt. `getBaseURL` is invoked defensively (it may be absent or throw on a
28
+ * partially-initialised client); any failure degrades to an empty baseURL.
29
+ */
30
+ export declare function buildSilentGuardKey(getBaseURL?: () => string | undefined): string;
31
+ //# sourceMappingURL=silentGuardKey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"silentGuardKey.d.ts","sourceRoot":"","sources":["../../../../src/utils/silentGuardKey.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,MAAM,CASjF"}
@@ -1 +1 @@
1
- {"version":3,"file":"SignInModal.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/SignInModal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAwD/B,eAAO,MAAM,eAAe,YAI3B,CAAC;AAEF,eAAO,MAAM,eAAe,YAI3B,CAAC;AAEF,eAAO,MAAM,oBAAoB,eAAqB,CAAC;AAEvD,4CAA4C;AAC5C,eAAO,MAAM,sBAAsB,GAAI,UAAU,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAGxF,CAAC;AAEF,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EA2WxB,CAAC;AA8FF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"SignInModal.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/SignInModal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAwD/B,eAAO,MAAM,eAAe,YAI3B,CAAC;AAEF,eAAO,MAAM,eAAe,YAI3B,CAAC;AAEF,eAAO,MAAM,oBAAoB,eAAqB,CAAC;AAEvD,4CAA4C;AAC5C,eAAO,MAAM,sBAAsB,GAAI,UAAU,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAGxF,CAAC;AAEF,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAsXxB,CAAC;AA8FF,eAAe,WAAW,CAAC"}
@@ -62,12 +62,16 @@ export interface OxyContextState {
62
62
  clearAllAccountData: () => Promise<void>;
63
63
  storageKeyPrefix: string;
64
64
  /**
65
- * Resolved human-readable app display name surfaced on the central Oxy
66
- * sign-in / consent experience (e.g. "Mention wants to access your Oxy
67
- * account"). Always non-empty derived from the `appName` prop, then
68
- * `storageKeyPrefix`, then `document.title` (web), then the platform.
65
+ * The app's Oxy OAuth client id / ApplicationCredential publicKey, as
66
+ * supplied via the `clientId` prop. Required for the cross-app device
67
+ * sign-in flow: the sign-in components send it to
68
+ * `POST /auth/session/create` so the API can identify the requesting app by
69
+ * its real registered client id (the consent identity is then resolved
70
+ * server-side and shown by the central auth web). `null` when the consuming
71
+ * app did not configure a client id — the device sign-in flow surfaces a
72
+ * configuration error in that case.
69
73
  */
70
- appName: string;
74
+ clientId: string | null;
71
75
  oxyServices: OxyServices;
72
76
  useFollow?: UseFollowHook;
73
77
  showBottomSheet?: (screenOrConfig: RouteName | {
@@ -90,10 +94,10 @@ export interface OxyContextProviderProps {
90
94
  authRedirectUri?: string;
91
95
  storageKeyPrefix?: string;
92
96
  /**
93
- * Human-readable name of the consuming app shown on the central Oxy
94
- * sign-in / consent experience. See {@link OxyContextState.appName}.
97
+ * The app's Oxy OAuth client id / ApplicationCredential publicKey; required
98
+ * for the cross-app device sign-in flow. See {@link OxyContextState.clientId}.
95
99
  */
96
- appName?: string;
100
+ clientId?: string;
97
101
  onAuthStateChange?: (user: User | null) => void;
98
102
  onError?: (error: ApiError) => void;
99
103
  }
@@ -1 +1 @@
1
- {"version":3,"file":"OxyContext.d.ts","sourceRoot":"","sources":["../../../../../src/ui/context/OxyContext.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"OxyContext.d.ts","sourceRoot":"","sources":["../../../../../src/ui/context/OxyContext.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAccountMutations.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/hooks/mutations/useAccountMutations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAccountMutations.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/hooks/mutations/useAccountMutations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,IAAI,EACJ,eAAe,EAChB,MAAM,aAAa,CAAC;AAcrB;;GAEG;AACH,eAAO,MAAM,gBAAgB;;EA6F5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe;SAMQ,MAAM;WAAS,MAAM;WAAS,MAAM;WAAS,MAAM;;;EA4EtF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,UAAU,8BAA8B;IACtC,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAClC;;;;OAIG;IACH,WAAW,EAAE,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB;sBAoFf,OAAO,CAAC,eAAe,CAAC,KAAG,IAAI;2BAQpB,OAAO,CAAC,eAAe,CAAC,KAAG,OAAO,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;sBARnD,OAAO,CAAC,eAAe,CAAC,KAAG,IAAI;2BAQpB,OAAO,CAAC,eAAe,CAAC,KAAG,OAAO,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;sBARnD,OAAO,CAAC,eAAe,CAAC,KAAG,IAAI;2BAQpB,OAAO,CAAC,eAAe,CAAC,KAAG,OAAO,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;sBARnD,OAAO,CAAC,eAAe,CAAC,KAAG,IAAI;2BAQpB,OAAO,CAAC,eAAe,CAAC,KAAG,OAAO,CAAC,IAAI,CAAC;;;;;;;;;;iBAjP1D,CAAC;gBAEV,CADH;gBAAsB,CAAC;;;;;;;;;;iBAMjB,CAAA;uBAA6B,CAAC;iBAAuB,CAAC;;;;qBAGnD,CAAC;qBAA2B,CAAC;;;;;;;;;oBAMhC,CAAA;kBAAwB,CAAC;mBAAyB,CAAC;;;mBAC1B,CAAC;;;;;;;;;;;;;;;;;;;;;;CAwOlC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB;cAMoB,OAAO,CAAC,eAAe,CAAC;aAAW,MAAM;;;;cAgJjG,CAAC;AAEF,4CAA4C;AAC5C,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;CACxI;AAED,4EAA4E;AAC5E,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,eAAO,MAAM,gCAAgC;;EAmD5C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;;EA+CpC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,uFAoBlC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa;UAWd,gBAAgB;iBACT,SAAS,GAAG,QAAQ,GAAG,UAAU;eACnC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;iBACrB,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI;WAS5C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useWebSSO.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useWebSSO.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,UAAU,gBAAgB;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACrD,2DAA2D;IAC3D,eAAe,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC5D,uCAAuC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAgCD;;GAEG;AACH,iBAAS,YAAY,IAAI,OAAO,CAI/B;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,EACxB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,OAAO,EACP,OAAc,GACf,EAAE,gBAAgB,GAAG,eAAe,CAwHpC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"useWebSSO.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useWebSSO.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD,UAAU,gBAAgB;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACrD,2DAA2D;IAC3D,eAAe,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC5D,uCAAuC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AA8BD;;GAEG;AACH,iBAAS,YAAY,IAAI,OAAO,CAI/B;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,EACxB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,OAAO,EACP,OAAc,GACf,EAAE,gBAAgB,GAAG,eAAe,CAwHpC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"OxyAuthScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/OxyAuthScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AA0F3D,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA6X5C,CAAC;AA6FF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"OxyAuthScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/OxyAuthScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AA0F3D,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAwY5C,CAAC;AA6FF,eAAe,aAAa,CAAC"}
@@ -30,13 +30,15 @@ export interface OxyProviderProps {
30
30
  onAuthStateChange?: (user: unknown) => void;
31
31
  storageKeyPrefix?: string;
32
32
  /**
33
- * Human-readable name of the consuming app (e.g. "Mention", "Homiio").
34
- * Surfaced on the central Oxy sign-in / consent experience as
35
- * "{appName} wants to access your Oxy account". When omitted, the SDK
36
- * derives a name from `storageKeyPrefix`, then `document.title` (web),
37
- * falling back to the platform. Set this to guarantee correct branding.
33
+ * The app's Oxy OAuth client id / ApplicationCredential publicKey.
34
+ * Required for the cross-app device sign-in flow: the QR / popup
35
+ * sign-in registers a device-flow session via `POST /auth/session/create`,
36
+ * which now identifies the requesting app by this real registered
37
+ * client id. The central Oxy auth experience resolves and renders the
38
+ * consent identity from it server-side. Without it the device sign-in
39
+ * flow cannot start.
38
40
  */
39
- appName?: string;
41
+ clientId?: string;
40
42
  baseURL?: string;
41
43
  authWebUrl?: string;
42
44
  authRedirectUri?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../../../../src/ui/types/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAKtD,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,MAAM,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAE5B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACxE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAG9C,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAGlC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACrD,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAGjE,aAAa,CAAC,EAAE,SAAS,CAAC;IAG1B,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAGnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IAMtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC7B"}
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../../../../src/ui/types/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAKtD,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,MAAM,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAE5B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACxE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAG9C,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAGlC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACrD,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAGjE,aAAa,CAAC,EAAE,SAAS,CAAC;IAG1B,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAGnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IAMtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC7B"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Shared, pure helpers for building the `origin|baseURL` signature used as the
3
+ * module-level run-once guard key for cold-boot silent-SSO probes
4
+ * (`silentColdBootKey` in `OxyContext`, `ssoSignature` in `useWebSSO`).
5
+ *
6
+ * NATIVE SAFETY (the bug this fixes): React Native aliases a global `window`
7
+ * (it points at the JS global object), so `typeof window !== 'undefined'` is
8
+ * `true` on native — but `window.location` is `undefined`. Reading
9
+ * `window.location.origin` after only a `typeof window` check therefore throws
10
+ * `TypeError: Cannot read property 'origin' of undefined` on native. Because
11
+ * the key is built UNCONDITIONALLY at the top of the cold-boot path (before its
12
+ * try/catch), that throw escaped session restore entirely and broke
13
+ * cross-session restore on native. Both prior copies of the guard had the same
14
+ * insufficient `typeof window` check and were prone to drift, so the read is
15
+ * consolidated here behind a guard that also verifies `window.location`.
16
+ */
17
+ /**
18
+ * Read `window.location.origin` safely on every platform.
19
+ *
20
+ * Returns the browser origin on web, and the sentinel `'no-origin'` anywhere
21
+ * `window.location` is absent (React Native, SSR/Node). Never throws.
22
+ */
23
+ export declare function safeWindowOrigin(): string;
24
+ /**
25
+ * Build the stable `origin|baseURL` signature for the silent-SSO run-once
26
+ * guard. Two providers pointed at the same API from the same origin share one
27
+ * attempt. `getBaseURL` is invoked defensively (it may be absent or throw on a
28
+ * partially-initialised client); any failure degrades to an empty baseURL.
29
+ */
30
+ export declare function buildSilentGuardKey(getBaseURL?: () => string | undefined): string;
31
+ //# sourceMappingURL=silentGuardKey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"silentGuardKey.d.ts","sourceRoot":"","sources":["../../../../src/utils/silentGuardKey.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,MAAM,CASjF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/services",
3
- "version": "8.7.0",
3
+ "version": "10.0.0",
4
4
  "description": "OxyHQ Expo/React Native SDK — UI components, screens, and native features",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -160,7 +160,7 @@
160
160
  "peerDependencies": {
161
161
  "@expo/vector-icons": "^15.0.3",
162
162
  "@oxyhq/bloom": ">=0.5.0",
163
- "@oxyhq/core": "^2.4.1",
163
+ "@oxyhq/core": "^3.2.0",
164
164
  "@react-native-community/netinfo": "^11.4.1",
165
165
  "@tanstack/query-async-storage-persister": "^5.100",
166
166
  "@tanstack/query-sync-storage-persister": "^5.100",
@@ -103,7 +103,7 @@ const OxyProvider: FC<OxyProviderProps> = ({
103
103
  children,
104
104
  onAuthStateChange,
105
105
  storageKeyPrefix,
106
- appName,
106
+ clientId,
107
107
  baseURL,
108
108
  authWebUrl,
109
109
  authRedirectUri,
@@ -297,7 +297,7 @@ const OxyProvider: FC<OxyProviderProps> = ({
297
297
  authWebUrl={authWebUrl}
298
298
  authRedirectUri={authRedirectUri}
299
299
  storageKeyPrefix={storageKeyPrefix}
300
- appName={appName}
300
+ clientId={clientId}
301
301
  onAuthStateChange={onAuthStateChange as OxyContextProviderProps['onAuthStateChange']}
302
302
  >
303
303
  {children}
@@ -93,7 +93,7 @@ const SignInModal: React.FC = () => {
93
93
 
94
94
  const insets = useSafeAreaInsets();
95
95
  const theme = useTheme();
96
- const { oxyServices, switchSession, appName } = useOxy();
96
+ const { oxyServices, switchSession, clientId } = useOxy();
97
97
 
98
98
  const socketRef = useRef<Socket | null>(null);
99
99
  const pollingIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
@@ -266,6 +266,17 @@ const SignInModal: React.FC = () => {
266
266
  setError(null);
267
267
  isProcessingRef.current = false;
268
268
 
269
+ // The cross-app device sign-in flow identifies the requesting app by its
270
+ // real registered OAuth client id (ApplicationCredential publicKey).
271
+ // Without it the API cannot resolve the consent identity, so we fail
272
+ // fast with a clear configuration error rather than creating a session
273
+ // the server would reject.
274
+ if (!clientId) {
275
+ setError('This app is not configured for sign-in (missing clientId).');
276
+ setIsLoading(false);
277
+ return;
278
+ }
279
+
269
280
  try {
270
281
  const sessionToken = generateSessionToken();
271
282
  const expiresAt = Date.now() + AUTH_SESSION_EXPIRY_MS;
@@ -273,7 +284,7 @@ const SignInModal: React.FC = () => {
273
284
  await oxyServices.makeRequest('POST', '/auth/session/create', {
274
285
  sessionToken,
275
286
  expiresAt,
276
- appId: appName,
287
+ clientId,
277
288
  }, { cache: false });
278
289
 
279
290
  setAuthSession({ sessionToken, expiresAt });
@@ -284,7 +295,7 @@ const SignInModal: React.FC = () => {
284
295
  } finally {
285
296
  setIsLoading(false);
286
297
  }
287
- }, [oxyServices, connectSocket, appName]);
298
+ }, [oxyServices, connectSocket, clientId]);
288
299
 
289
300
  // Generate a cryptographically random session token.
290
301
  // 16 random bytes -> 32 hex chars (128 bits of entropy) — unguessable.
@@ -42,7 +42,6 @@ import { useDeviceManagement } from '../hooks/useDeviceManagement';
42
42
  import { getStorageKeys, createPlatformStorage, type StorageInterface } from '../utils/storageHelpers';
43
43
  import { isInvalidSessionError, isTimeoutOrNetworkError } from '../utils/errorHandlers';
44
44
  import { readActiveAuthuser, writeActiveAuthuser } from '../utils/activeAuthuser';
45
- import { resolveAppDisplayName } from '../utils/appName';
46
45
  import type { RouteName } from '../navigation/routes';
47
46
  import { showBottomSheet as globalShowBottomSheet } from '../navigation/bottomSheetManager';
48
47
  import { useQueryClient } from '@tanstack/react-query';
@@ -51,6 +50,7 @@ import { useAvatarPicker } from '../hooks/useAvatarPicker';
51
50
  import { useAccountStore } from '../stores/accountStore';
52
51
  import { logger as loggerUtil } from '@oxyhq/core';
53
52
  import { useWebSSO, isWebBrowser } from '../hooks/useWebSSO';
53
+ import { buildSilentGuardKey } from '../../utils/silentGuardKey';
54
54
 
55
55
  export interface OxyContextState {
56
56
  user: User | null;
@@ -116,12 +116,16 @@ export interface OxyContextState {
116
116
  clearAllAccountData: () => Promise<void>;
117
117
  storageKeyPrefix: string;
118
118
  /**
119
- * Resolved human-readable app display name surfaced on the central Oxy
120
- * sign-in / consent experience (e.g. "Mention wants to access your Oxy
121
- * account"). Always non-empty derived from the `appName` prop, then
122
- * `storageKeyPrefix`, then `document.title` (web), then the platform.
119
+ * The app's Oxy OAuth client id / ApplicationCredential publicKey, as
120
+ * supplied via the `clientId` prop. Required for the cross-app device
121
+ * sign-in flow: the sign-in components send it to
122
+ * `POST /auth/session/create` so the API can identify the requesting app by
123
+ * its real registered client id (the consent identity is then resolved
124
+ * server-side and shown by the central auth web). `null` when the consuming
125
+ * app did not configure a client id — the device sign-in flow surfaces a
126
+ * configuration error in that case.
123
127
  */
124
- appName: string;
128
+ clientId: string | null;
125
129
  oxyServices: OxyServices;
126
130
  useFollow?: UseFollowHook;
127
131
  showBottomSheet?: (screenOrConfig: RouteName | { screen: RouteName; props?: Record<string, unknown> }) => void;
@@ -149,10 +153,10 @@ export interface OxyContextProviderProps {
149
153
  authRedirectUri?: string;
150
154
  storageKeyPrefix?: string;
151
155
  /**
152
- * Human-readable name of the consuming app shown on the central Oxy
153
- * sign-in / consent experience. See {@link OxyContextState.appName}.
156
+ * The app's Oxy OAuth client id / ApplicationCredential publicKey; required
157
+ * for the cross-app device sign-in flow. See {@link OxyContextState.clientId}.
154
158
  */
155
- appName?: string;
159
+ clientId?: string;
156
160
  onAuthStateChange?: (user: User | null) => void;
157
161
  onError?: (error: ApiError) => void;
158
162
  }
@@ -181,14 +185,15 @@ const servicesSilentAttempted = new Set<string>();
181
185
  * Build the `origin|baseURL` signature used as the silent-cold-boot guard key.
182
186
  */
183
187
  function silentColdBootKey(oxyServices: OxyServices): string {
184
- const origin = typeof window !== 'undefined' ? window.location.origin : 'no-origin';
185
- let baseURL = '';
186
- try {
187
- baseURL = oxyServices.getBaseURL?.() ?? '';
188
- } catch {
189
- baseURL = '';
190
- }
191
- return `${origin}|${baseURL}`;
188
+ // `buildSilentGuardKey` reads `window.location.origin` behind a guard that
189
+ // also verifies `window.location` exists. This is critical: it runs
190
+ // UNCONDITIONALLY at the top of `restoreSessionsFromStorage` (before the
191
+ // cold-boot try/catch) on EVERY platform, and React Native aliases a global
192
+ // `window` with NO `window.location`. Without that guard the read threw
193
+ // `Cannot read property 'origin' of undefined` on native, escaping the
194
+ // restore path so `markAuthResolved` never ran and stored-session restore was
195
+ // never reached.
196
+ return buildSilentGuardKey(() => oxyServices.getBaseURL?.());
192
197
  }
193
198
 
194
199
  /**
@@ -258,7 +263,12 @@ const COLD_BOOT_OVERALL_DEADLINE = 20000;
258
263
  * off-browser.
259
264
  */
260
265
  function isSameSiteIdP(idpOrigin: string): boolean {
261
- if (typeof window === 'undefined') return false;
266
+ // Native defines a global `window` but no `window.location`; guard the
267
+ // latter so reading `.hostname` can never throw off-browser. (Only reachable
268
+ // from the web-only visibility check, but kept robust for parity.)
269
+ if (typeof window === 'undefined' || typeof window.location === 'undefined') {
270
+ return false;
271
+ }
262
272
  let idpHostname: string;
263
273
  try {
264
274
  idpHostname = new URL(idpOrigin).hostname;
@@ -314,7 +324,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
314
324
  authWebUrl,
315
325
  authRedirectUri,
316
326
  storageKeyPrefix = 'oxy_session',
317
- appName: appNameProp,
327
+ clientId: clientIdProp,
318
328
  onAuthStateChange,
319
329
  onError,
320
330
  }) => {
@@ -424,13 +434,16 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
424
434
 
425
435
  const storageKeys = useMemo(() => getStorageKeys(storageKeyPrefix), [storageKeyPrefix]);
426
436
 
427
- // Human-readable app display name for the central sign-in / consent UI.
428
- // Derived once from the consumer config; never "web" unless the app supplies
429
- // no name, no custom prefix, and no document title.
430
- const appName = useMemo(
431
- () => resolveAppDisplayName(appNameProp, storageKeyPrefix),
432
- [appNameProp, storageKeyPrefix],
433
- );
437
+ // The app's Oxy OAuth client id surfaced on the context so the cross-app
438
+ // device sign-in components (SignInModal / OxyAuthScreen) can identify the
439
+ // requesting app to `POST /auth/session/create`. Normalized to a trimmed
440
+ // non-empty string, or `null` when the consumer did not configure one — the
441
+ // sign-in components surface a clear configuration error in that case rather
442
+ // than falling back to any display string.
443
+ const clientId = useMemo(() => {
444
+ const trimmed = clientIdProp?.trim();
445
+ return trimmed ? trimmed : null;
446
+ }, [clientIdProp]);
434
447
 
435
448
  // Storage initialization.
436
449
  //
@@ -1666,7 +1679,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
1666
1679
  clearSessionState,
1667
1680
  clearAllAccountData,
1668
1681
  storageKeyPrefix,
1669
- appName,
1682
+ clientId,
1670
1683
  oxyServices,
1671
1684
  useFollow: useFollowHook,
1672
1685
  showBottomSheet: showBottomSheetForContext,
@@ -1695,7 +1708,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
1695
1708
  logoutAllDeviceSessions,
1696
1709
  oxyServices,
1697
1710
  storageKeyPrefix,
1698
- appName,
1711
+ clientId,
1699
1712
  refreshSessionsWithUser,
1700
1713
  sessions,
1701
1714
  setLanguage,
@@ -1773,7 +1786,7 @@ const LOADING_STATE: OxyContextState = {
1773
1786
  clearSessionState: () => rejectMissingProvider<void>(),
1774
1787
  clearAllAccountData: () => rejectMissingProvider<void>(),
1775
1788
  storageKeyPrefix: 'oxy_session',
1776
- appName: resolveAppDisplayName(undefined, undefined),
1789
+ clientId: null,
1777
1790
  oxyServices: LOADING_STATE_OXY_SERVICES,
1778
1791
  openAvatarPicker: () => {},
1779
1792
  actingAs: null,
@@ -18,6 +18,7 @@
18
18
  import { useEffect, useRef, useCallback } from 'react';
19
19
  import type { OxyServices } from '@oxyhq/core';
20
20
  import type { SessionLoginResponse } from '@oxyhq/core';
21
+ import { buildSilentGuardKey } from '../../utils/silentGuardKey';
21
22
 
22
23
  interface UseWebSSOOptions {
23
24
  oxyServices: OxyServices;
@@ -58,14 +59,12 @@ const silentSSOAttempted = new Set<string>();
58
59
  * pointed at the same API from the same origin share one attempt.
59
60
  */
60
61
  function ssoSignature(oxyServices: OxyServices): string {
61
- const origin = typeof window !== 'undefined' ? window.location.origin : 'no-origin';
62
- let baseURL = '';
63
- try {
64
- baseURL = oxyServices.getBaseURL?.() ?? '';
65
- } catch {
66
- baseURL = '';
67
- }
68
- return `${origin}|${baseURL}`;
62
+ // Shared with `OxyContext.silentColdBootKey`. `buildSilentGuardKey` reads
63
+ // `window.location.origin` behind a guard that also verifies
64
+ // `window.location` exists — React Native aliases a global `window` with NO
65
+ // `window.location`, so a `typeof window`-only check would throw
66
+ // `Cannot read property 'origin' of undefined` off-browser.
67
+ return buildSilentGuardKey(() => oxyServices.getBaseURL?.());
69
68
  }
70
69
 
71
70
  /**
@@ -119,7 +119,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
119
119
  theme,
120
120
  }) => {
121
121
  const bloomTheme = useTheme();
122
- const { oxyServices, signIn, switchSession, appName } = useOxy();
122
+ const { oxyServices, signIn, switchSession, clientId } = useOxy();
123
123
 
124
124
  const [authSession, setAuthSession] = useState<AuthSession | null>(null);
125
125
  const [isLoading, setIsLoading] = useState(true);
@@ -264,6 +264,17 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
264
264
  setError(null);
265
265
  isProcessingRef.current = false;
266
266
 
267
+ // The cross-app device sign-in flow identifies the requesting app by its
268
+ // real registered OAuth client id (ApplicationCredential publicKey).
269
+ // Without it the API cannot resolve the consent identity, so we fail fast
270
+ // with a clear configuration error rather than creating a session the
271
+ // server would reject.
272
+ if (!clientId) {
273
+ setError('This app is not configured for sign-in (missing clientId).');
274
+ setIsLoading(false);
275
+ return;
276
+ }
277
+
267
278
  try {
268
279
  // Generate a unique session token for this auth request
269
280
  const sessionToken = generateSessionToken();
@@ -273,7 +284,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
273
284
  await oxyServices.makeRequest('POST', '/auth/session/create', {
274
285
  sessionToken,
275
286
  expiresAt,
276
- appId: appName,
287
+ clientId,
277
288
  }, { cache: false });
278
289
 
279
290
  setAuthSession({ sessionToken, expiresAt });
@@ -286,7 +297,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
286
297
  } finally {
287
298
  setIsLoading(false);
288
299
  }
289
- }, [oxyServices, connectSocket, appName]);
300
+ }, [oxyServices, connectSocket, clientId]);
290
301
 
291
302
  // Generate a random session token
292
303
  const generateSessionToken = (): string => {
@@ -53,13 +53,15 @@ export interface OxyProviderProps {
53
53
  onAuthStateChange?: (user: unknown) => void;
54
54
  storageKeyPrefix?: string;
55
55
  /**
56
- * Human-readable name of the consuming app (e.g. "Mention", "Homiio").
57
- * Surfaced on the central Oxy sign-in / consent experience as
58
- * "{appName} wants to access your Oxy account". When omitted, the SDK
59
- * derives a name from `storageKeyPrefix`, then `document.title` (web),
60
- * falling back to the platform. Set this to guarantee correct branding.
56
+ * The app's Oxy OAuth client id / ApplicationCredential publicKey.
57
+ * Required for the cross-app device sign-in flow: the QR / popup
58
+ * sign-in registers a device-flow session via `POST /auth/session/create`,
59
+ * which now identifies the requesting app by this real registered
60
+ * client id. The central Oxy auth experience resolves and renders the
61
+ * consent identity from it server-side. Without it the device sign-in
62
+ * flow cannot start.
61
63
  */
62
- appName?: string;
64
+ clientId?: string;
63
65
  baseURL?: string;
64
66
  authWebUrl?: string;
65
67
  authRedirectUri?: string;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @jest-environment node
3
+ *
4
+ * Regression coverage for the native session-restore crash:
5
+ *
6
+ * W [component:OxyContext]: Failed to restore sessions from storage
7
+ * [TypeError: Cannot read property 'origin' of undefined]
8
+ *
9
+ * `silentColdBootKey` (OxyContext) and `ssoSignature` (useWebSSO) both build an
10
+ * `origin|baseURL` guard signature UNCONDITIONALLY at the top of the cold-boot
11
+ * path, on every platform. React Native aliases a global `window` (so
12
+ * `typeof window !== 'undefined'` is `true`) but provides NO `window.location`.
13
+ * The previous `typeof window`-only guard then read `window.location.origin`
14
+ * and threw `Cannot read property 'origin' of undefined`, escaping session
15
+ * restore entirely. Both call sites now delegate to the shared, guarded
16
+ * `buildSilentGuardKey`, verified here under all three platform shapes.
17
+ *
18
+ * Runs in the `node` environment so `window` is genuinely controllable — under
19
+ * jsdom `window.location` is non-configurable and cannot be removed, so the
20
+ * native shape (window present, location absent) is not reproducible there.
21
+ */
22
+
23
+ import { buildSilentGuardKey, safeWindowOrigin } from '../silentGuardKey';
24
+
25
+ describe('silentGuardKey native safety', () => {
26
+ const globalRef = globalThis as { window?: unknown };
27
+
28
+ afterEach(() => {
29
+ delete globalRef.window;
30
+ });
31
+
32
+ describe('safeWindowOrigin', () => {
33
+ it('returns "no-origin" when there is no window (Node / SSR)', () => {
34
+ delete globalRef.window;
35
+ expect(safeWindowOrigin()).toBe('no-origin');
36
+ });
37
+
38
+ it('returns "no-origin" on React Native (window present, no location)', () => {
39
+ // EXACT native shape: RN aliases a global `window` to the JS global, but
40
+ // there is no `window.location`. The old `typeof window`-only guard threw
41
+ // here; the new guard must return the sentinel without throwing.
42
+ globalRef.window = {};
43
+ expect(() => safeWindowOrigin()).not.toThrow();
44
+ expect(safeWindowOrigin()).toBe('no-origin');
45
+ });
46
+
47
+ it('returns the browser origin on web', () => {
48
+ globalRef.window = { location: { origin: 'https://app.mention.earth' } };
49
+ expect(safeWindowOrigin()).toBe('https://app.mention.earth');
50
+ });
51
+ });
52
+
53
+ describe('buildSilentGuardKey', () => {
54
+ it('does not throw and composes "no-origin|" on React Native', () => {
55
+ globalRef.window = {};
56
+ const getBaseURL = () => 'https://api.mention.earth';
57
+ expect(() => buildSilentGuardKey(getBaseURL)).not.toThrow();
58
+ expect(buildSilentGuardKey(getBaseURL)).toBe('no-origin|https://api.mention.earth');
59
+ });
60
+
61
+ it('composes "origin|baseURL" on web', () => {
62
+ globalRef.window = { location: { origin: 'https://app.mention.earth' } };
63
+ expect(buildSilentGuardKey(() => 'https://api.mention.earth')).toBe(
64
+ 'https://app.mention.earth|https://api.mention.earth',
65
+ );
66
+ });
67
+
68
+ it('degrades baseURL to empty when getBaseURL is absent', () => {
69
+ globalRef.window = {};
70
+ expect(buildSilentGuardKey()).toBe('no-origin|');
71
+ });
72
+
73
+ it('degrades baseURL to empty when getBaseURL throws', () => {
74
+ globalRef.window = {};
75
+ const throwing = (): string => {
76
+ throw new Error('client not initialised');
77
+ };
78
+ expect(() => buildSilentGuardKey(throwing)).not.toThrow();
79
+ expect(buildSilentGuardKey(throwing)).toBe('no-origin|');
80
+ });
81
+ });
82
+ });