@oxy.so/core 4.5.0-oxy-one.1 → 4.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.
- package/README.md +1 -1
- package/dist/cjs/HttpService.js +63 -19
- package/dist/cjs/api/accounts.js +10 -3
- package/dist/cjs/api/agency.js +3 -1
- package/dist/cjs/api/apps.js +15 -4
- package/dist/cjs/api/assets.js +39 -11
- package/dist/cjs/api/auth.js +28 -8
- package/dist/cjs/api/billing.js +24 -7
- package/dist/cjs/api/civic.js +14 -4
- package/dist/cjs/api/follows.js +9 -2
- package/dist/cjs/api/identity.js +31 -9
- package/dist/cjs/api/nodes.js +3 -1
- package/dist/cjs/api/privacy.js +8 -2
- package/dist/cjs/api/session.js +15 -4
- package/dist/cjs/api/store.js +15 -5
- package/dist/cjs/api/topics.js +10 -3
- package/dist/cjs/api/users.js +16 -4
- package/dist/cjs/boot/sessionColdBoot.js +40 -13
- package/dist/cjs/constants/version.js +6 -6
- package/dist/cjs/crypto/identityMarker.js +3 -1
- package/dist/cjs/crypto/identityProof.js +6 -1
- package/dist/cjs/crypto/keyManager.js +87 -32
- package/dist/cjs/crypto/recoveryPhrase.js +2 -2
- package/dist/cjs/crypto/signatureService.js +3 -4
- package/dist/cjs/i18n/index.js +16 -3
- package/dist/cjs/i18n/locales/ar-SA.js +366 -366
- package/dist/cjs/i18n/locales/ca-ES.js +366 -366
- package/dist/cjs/i18n/locales/de-DE.js +366 -366
- package/dist/cjs/i18n/locales/en-US.js +1994 -1994
- package/dist/cjs/i18n/locales/es-ES.js +1994 -1994
- package/dist/cjs/i18n/locales/fr-FR.js +366 -366
- package/dist/cjs/i18n/locales/it-IT.js +366 -366
- package/dist/cjs/i18n/locales/ja-JP.js +366 -366
- package/dist/cjs/i18n/locales/ko-KR.js +366 -366
- package/dist/cjs/i18n/locales/pt-PT.js +366 -366
- package/dist/cjs/i18n/locales/zh-CN.js +366 -366
- package/dist/cjs/inference/OxyInferenceClient.js +12 -18
- package/dist/cjs/models/interfaces.js +11 -11
- package/dist/cjs/server/OxyServer.js +86 -28
- package/dist/cjs/server/agentAccount.js +6 -2
- package/dist/cjs/server/aliaMachineCredential.js +39 -14
- package/dist/cjs/server/auth.js +5 -4
- package/dist/cjs/server/capabilityTicket.js +5 -5
- package/dist/cjs/server/index.js +2 -1
- package/dist/cjs/server/liveCapabilityTicket.js +4 -1
- package/dist/cjs/server/middleware.js +61 -42
- package/dist/cjs/server/namespaces.js +28 -7
- package/dist/cjs/server/requesterAssertion.js +36 -30
- package/dist/cjs/server/serviceTokenLifetime.js +7 -4
- package/dist/cjs/server/traffic.js +53 -14
- package/dist/cjs/server/trafficNodeHttp.js +33 -8
- package/dist/cjs/server/workloadIdentity.client.js +4 -0
- package/dist/cjs/server/workloadIdentity.js +28 -1
- package/dist/cjs/session/SessionClient.js +54 -17
- package/dist/cjs/session/accountDelegationAccess.js +4 -6
- package/dist/cjs/session/accountDialogController.js +1 -1
- package/dist/cjs/session/authStateStore.js +18 -9
- package/dist/cjs/session/identityPin.js +6 -2
- package/dist/cjs/session/refresh.js +81 -23
- package/dist/cjs/session/sharedDeviceCredential.js +28 -15
- package/dist/cjs/shared/utils/errorUtils.js +1 -1
- package/dist/cjs/shared/utils/networkUtils.js +1 -1
- package/dist/cjs/shared/utils/themeUtils.js +1 -1
- package/dist/cjs/utils/accountCacheSweep.js +3 -1
- package/dist/cjs/utils/accountUtils.js +1 -3
- package/dist/cjs/utils/asyncUtils.js +1 -1
- package/dist/cjs/utils/authHelpers.js +2 -1
- package/dist/cjs/utils/avatarUtils.js +4 -2
- package/dist/cjs/utils/cache.js +1 -1
- package/dist/cjs/utils/cacheKey.js +3 -1
- package/dist/cjs/utils/deviceManager.js +4 -4
- package/dist/cjs/utils/errorUtils.js +6 -4
- package/dist/cjs/utils/languageUtils.js +404 -57
- package/dist/cjs/utils/profileLinks.js +1 -3
- package/dist/cjs/utils/requestUtils.js +7 -1
- package/dist/cjs/utils/userIdentity.js +1 -1
- package/dist/cjs/utils/validationUtils.js +5 -6
- package/dist/esm/HttpService.js +64 -20
- package/dist/esm/api/accounts.js +11 -4
- package/dist/esm/api/agency.js +3 -1
- package/dist/esm/api/apps.js +15 -4
- package/dist/esm/api/assets.js +39 -11
- package/dist/esm/api/auth.js +28 -8
- package/dist/esm/api/billing.js +25 -8
- package/dist/esm/api/civic.js +14 -4
- package/dist/esm/api/follows.js +9 -2
- package/dist/esm/api/identity.js +31 -9
- package/dist/esm/api/nodes.js +3 -1
- package/dist/esm/api/privacy.js +8 -2
- package/dist/esm/api/session.js +15 -4
- package/dist/esm/api/store.js +15 -5
- package/dist/esm/api/topics.js +10 -3
- package/dist/esm/api/users.js +16 -4
- package/dist/esm/boot/sessionColdBoot.js +41 -14
- package/dist/esm/constants/version.js +6 -6
- package/dist/esm/crypto/identityMarker.js +3 -1
- package/dist/esm/crypto/identityProof.js +6 -1
- package/dist/esm/crypto/internal.js +1 -1
- package/dist/esm/crypto/keyManager.js +87 -32
- package/dist/esm/crypto/recoveryPhrase.js +2 -2
- package/dist/esm/crypto/signatureService.js +3 -4
- package/dist/esm/i18n/index.js +16 -3
- package/dist/esm/i18n/locales/ar-SA.js +366 -366
- package/dist/esm/i18n/locales/ca-ES.js +366 -366
- package/dist/esm/i18n/locales/de-DE.js +366 -366
- package/dist/esm/i18n/locales/en-US.js +1994 -1994
- package/dist/esm/i18n/locales/es-ES.js +1994 -1994
- package/dist/esm/i18n/locales/fr-FR.js +366 -366
- package/dist/esm/i18n/locales/it-IT.js +366 -366
- package/dist/esm/i18n/locales/ja-JP.js +366 -366
- package/dist/esm/i18n/locales/ko-KR.js +366 -366
- package/dist/esm/i18n/locales/pt-PT.js +366 -366
- package/dist/esm/i18n/locales/zh-CN.js +366 -366
- package/dist/esm/index.js +1 -1
- package/dist/esm/inference/OxyInferenceClient.js +13 -19
- package/dist/esm/models/interfaces.js +11 -11
- package/dist/esm/server/OxyServer.js +87 -29
- package/dist/esm/server/agentAccount.js +6 -2
- package/dist/esm/server/aliaMachineCredential.js +39 -14
- package/dist/esm/server/auth.js +6 -5
- package/dist/esm/server/capabilityTicket.js +6 -6
- package/dist/esm/server/index.js +5 -5
- package/dist/esm/server/liveCapabilityTicket.js +6 -3
- package/dist/esm/server/middleware.js +62 -43
- package/dist/esm/server/namespaces.js +31 -10
- package/dist/esm/server/requesterAssertion.js +36 -30
- package/dist/esm/server/serviceTokenLifetime.js +7 -4
- package/dist/esm/server/traffic.js +55 -16
- package/dist/esm/server/trafficNodeHttp.js +34 -9
- package/dist/esm/server/userInvalidation.js +1 -1
- package/dist/esm/server/workloadIdentity.client.js +3 -0
- package/dist/esm/server/workloadIdentity.js +27 -1
- package/dist/esm/session/SessionClient.js +54 -17
- package/dist/esm/session/accountDelegationAccess.js +5 -7
- package/dist/esm/session/accountDialogController.js +1 -1
- package/dist/esm/session/authStateStore.js +18 -9
- package/dist/esm/session/identityPin.js +6 -2
- package/dist/esm/session/refresh.js +82 -24
- package/dist/esm/session/sharedDeviceCredential.js +28 -15
- package/dist/esm/shared/utils/errorUtils.js +1 -1
- package/dist/esm/shared/utils/networkUtils.js +1 -1
- package/dist/esm/shared/utils/themeUtils.js +1 -1
- package/dist/esm/utils/accountCacheSweep.js +3 -1
- package/dist/esm/utils/accountUtils.js +1 -3
- package/dist/esm/utils/asyncUtils.js +1 -1
- package/dist/esm/utils/authHelpers.js +2 -1
- package/dist/esm/utils/avatarUtils.js +4 -2
- package/dist/esm/utils/cache.js +1 -1
- package/dist/esm/utils/cacheKey.js +3 -1
- package/dist/esm/utils/deviceManager.js +4 -4
- package/dist/esm/utils/errorUtils.js +6 -4
- package/dist/esm/utils/languageUtils.js +404 -57
- package/dist/esm/utils/profileLinks.js +1 -3
- package/dist/esm/utils/requestUtils.js +7 -1
- package/dist/esm/utils/userIdentity.js +1 -1
- package/dist/esm/utils/validationUtils.js +5 -6
- package/dist/types/HttpService.d.ts +1 -1
- package/dist/types/api/accounts.d.ts +16 -3
- package/dist/types/api/apps.d.ts +4 -4
- package/dist/types/crypto/internal.d.ts +1 -1
- package/dist/types/index.d.ts +4 -4
- package/dist/types/models/interfaces.d.ts +9 -1
- package/dist/types/server/index.d.ts +6 -6
- package/dist/types/server/workloadIdentity.client.d.ts +5 -1
- package/dist/types/server/workloadIdentity.d.ts +26 -0
- package/dist/types/session/accountDelegationAccess.d.ts +1 -1
- package/dist/types/session/index.d.ts +1 -1
- package/dist/types/utils/userIdentity.d.ts +1 -1
- package/dist/types/utils/validationUtils.d.ts +4 -5
- package/package.json +3 -4
- package/src/HttpService.ts +183 -53
- package/src/OxyServices.errors.ts +7 -3
- package/src/OxyServices.ts +6 -2
- package/src/api/accounts.ts +96 -28
- package/src/api/agency.ts +24 -9
- package/src/api/appData.ts +12 -2
- package/src/api/apps.ts +81 -31
- package/src/api/assets.ts +113 -43
- package/src/api/auth.ts +145 -77
- package/src/api/billing.ts +112 -65
- package/src/api/civic.ts +61 -19
- package/src/api/contacts.ts +4 -1
- package/src/api/devices.ts +54 -21
- package/src/api/follows.ts +88 -31
- package/src/api/identity.ts +101 -33
- package/src/api/linkedAccounts.ts +26 -8
- package/src/api/nodes.ts +18 -6
- package/src/api/notifications.ts +26 -6
- package/src/api/privacy.ts +42 -8
- package/src/api/reputation.ts +18 -7
- package/src/api/session.ts +23 -5
- package/src/api/store.ts +81 -31
- package/src/api/topics.ts +18 -6
- package/src/api/users.ts +98 -35
- package/src/boot/sessionColdBoot.ts +60 -19
- package/src/civic/payloads.ts +1 -4
- package/src/client/context.ts +6 -1
- package/src/constants/version.ts +7 -6
- package/src/crypto/aead.ts +1 -5
- package/src/crypto/ecdh.ts +1 -4
- package/src/crypto/identityDerivations.ts +5 -1
- package/src/crypto/identityMarker.ts +3 -1
- package/src/crypto/identityProof.ts +6 -1
- package/src/crypto/index.ts +11 -11
- package/src/crypto/internal.ts +6 -1
- package/src/crypto/keyManager.ts +348 -98
- package/src/crypto/recoveryPhrase.ts +14 -9
- package/src/crypto/registrationPow.ts +1 -1
- package/src/crypto/signatureService.ts +14 -6
- package/src/i18n/accountCategoryLabels.ts +1 -4
- package/src/i18n/accountRoleLabels.ts +1 -4
- package/src/i18n/index.ts +25 -7
- package/src/i18n/locales/ar-SA.ts +375 -366
- package/src/i18n/locales/ca-ES.ts +382 -366
- package/src/i18n/locales/de-DE.ts +387 -366
- package/src/i18n/locales/en-US.ts +2034 -1994
- package/src/i18n/locales/es-ES.ts +2043 -1994
- package/src/i18n/locales/fr-FR.ts +387 -366
- package/src/i18n/locales/it-IT.ts +380 -366
- package/src/i18n/locales/ja-JP.ts +380 -366
- package/src/i18n/locales/ko-KR.ts +377 -366
- package/src/i18n/locales/pt-PT.ts +383 -366
- package/src/i18n/locales/zh-CN.ts +373 -366
- package/src/i18n/trustTierLabels.ts +1 -4
- package/src/index.ts +371 -349
- package/src/inference/OxyInferenceClient.ts +784 -780
- package/src/models/interfaces.ts +39 -27
- package/src/server/OxyServer.ts +227 -68
- package/src/server/agentAccount.ts +8 -2
- package/src/server/aliaMachineCredential.ts +57 -16
- package/src/server/auth.ts +9 -5
- package/src/server/capabilityTicket.ts +30 -21
- package/src/server/index.ts +29 -6
- package/src/server/liveCapabilityTicket.ts +31 -9
- package/src/server/middleware.ts +212 -121
- package/src/server/namespaces.ts +247 -94
- package/src/server/rateLimit.ts +2 -4
- package/src/server/requesterAssertion.ts +93 -54
- package/src/server/serviceTokenLifetime.ts +9 -4
- package/src/server/traffic.ts +117 -23
- package/src/server/trafficNodeHttp.ts +61 -14
- package/src/server/userInvalidation.ts +1 -4
- package/src/server/workloadIdentity.client.ts +12 -1
- package/src/server/workloadIdentity.ts +52 -5
- package/src/session/SessionClient.ts +170 -49
- package/src/session/accountDelegationAccess.ts +24 -31
- package/src/session/accountDialogController.ts +59 -14
- package/src/session/accountSwitchTargets.ts +10 -15
- package/src/session/authStateStore.ts +121 -81
- package/src/session/deviceDirectory.ts +1 -3
- package/src/session/identityPin.ts +10 -11
- package/src/session/identitySession.ts +3 -1
- package/src/session/index.ts +87 -82
- package/src/session/refresh.ts +138 -44
- package/src/session/sessionClientHost.ts +1 -3
- package/src/session/sharedDeviceCredential.ts +35 -14
- package/src/session/socketLoader.ts +9 -2
- package/src/shared/utils/errorUtils.ts +5 -2
- package/src/shared/utils/networkUtils.ts +5 -8
- package/src/shared/utils/themeUtils.ts +2 -6
- package/src/types/buffer.d.ts +66 -21
- package/src/types/expo-secure-store.d.ts +5 -1
- package/src/utils/accountCacheSweep.ts +4 -5
- package/src/utils/accountUtils.ts +107 -108
- package/src/utils/apiUtils.ts +3 -3
- package/src/utils/asyncUtils.ts +2 -2
- package/src/utils/authHelpers.ts +10 -5
- package/src/utils/avatarUtils.ts +11 -6
- package/src/utils/cache.ts +9 -10
- package/src/utils/cacheKey.ts +5 -1
- package/src/utils/coldBoot.ts +1 -3
- package/src/utils/commonsDelivery.ts +1 -4
- package/src/utils/deviceManager.ts +15 -14
- package/src/utils/errorUtils.ts +68 -86
- package/src/utils/languageUtils.ts +407 -58
- package/src/utils/oauthPkce.ts +1 -4
- package/src/utils/platform.ts +0 -1
- package/src/utils/profileLinks.ts +2 -5
- package/src/utils/requestUtils.ts +18 -14
- package/src/utils/sessionUtils.ts +34 -33
- package/src/utils/userHandle.ts +3 -1
- package/src/utils/userIdentity.ts +1 -1
- package/src/utils/validationUtils.ts +11 -9
package/src/session/index.ts
CHANGED
|
@@ -18,7 +18,13 @@ export type { DeviceFingerprint, StoredDeviceInfo } from '../utils/deviceManager
|
|
|
18
18
|
// Session sync (device-scoped multi-account session client)
|
|
19
19
|
// ---------------------------------------------------------------------------
|
|
20
20
|
export { SessionClient } from './SessionClient';
|
|
21
|
-
export type {
|
|
21
|
+
export type {
|
|
22
|
+
TokenTransport,
|
|
23
|
+
SessionClientHost,
|
|
24
|
+
SessionClientOptions,
|
|
25
|
+
DeviceCredential,
|
|
26
|
+
SessionStateOrigin,
|
|
27
|
+
} from './SessionClient';
|
|
22
28
|
// Injectable for tests/specialized hosts; ordinary consumers use core's lazy
|
|
23
29
|
// transport and do not pull socket.io-client into their initial module graph.
|
|
24
30
|
export type { SocketIOFactory, MinimalSocket } from './socketLoader';
|
|
@@ -31,10 +37,10 @@ export type { SocketIOFactory, MinimalSocket } from './socketLoader';
|
|
|
31
37
|
export { createSessionClientHost } from './sessionClientHost';
|
|
32
38
|
export { createSessionClient } from './createSessionClient';
|
|
33
39
|
export {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
deviceStateToClientSessions,
|
|
41
|
+
activeSessionIdOf,
|
|
42
|
+
activeUserOf,
|
|
43
|
+
accountIdsOf,
|
|
38
44
|
} from './projectSessionState';
|
|
39
45
|
|
|
40
46
|
// Pure projections over the device DIRECTORY (`GET /session/device/directory`,
|
|
@@ -50,18 +56,18 @@ export {
|
|
|
50
56
|
// reached through two people is TWO rows under two humans, which a list keyed
|
|
51
57
|
// by account cannot say.
|
|
52
58
|
export {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
canActivateContext,
|
|
60
|
+
directoryDisplayName,
|
|
61
|
+
directoryHandle,
|
|
62
|
+
projectDevicePrincipals,
|
|
63
|
+
resolveActiveContext,
|
|
64
|
+
resolveDeviceContext,
|
|
59
65
|
} from './deviceDirectory';
|
|
60
66
|
export type {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
DeviceContext,
|
|
68
|
+
DeviceContextActor,
|
|
69
|
+
DeviceContextSubject,
|
|
70
|
+
DevicePrincipalGroup,
|
|
65
71
|
} from './deviceDirectory';
|
|
66
72
|
|
|
67
73
|
// The switcher's RENDER model over that projection — names, handles and avatar
|
|
@@ -70,9 +76,9 @@ export type {
|
|
|
70
76
|
// projection lived here before it.
|
|
71
77
|
export { buildSwitcherRows, showsPrincipalHeaders } from './deviceSwitcherRows';
|
|
72
78
|
export type {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
ResolveAvatarUrl,
|
|
80
|
+
SwitcherContextRow,
|
|
81
|
+
SwitcherPrincipalRow,
|
|
76
82
|
} from './deviceSwitcherRows';
|
|
77
83
|
|
|
78
84
|
// The switch-target predicates over the account GRAPH — a list of accounts to
|
|
@@ -83,16 +89,16 @@ export type {
|
|
|
83
89
|
// `AccountNode`s — the Console workspace switcher, managed-accounts rows — ask
|
|
84
90
|
// the SAME questions instead of testing a kind literal.
|
|
85
91
|
export {
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
isSwitchTargetAccount,
|
|
93
|
+
canSwitchIntoAccount,
|
|
88
94
|
} from './accountSwitchTargets';
|
|
89
95
|
|
|
90
96
|
// The service/agent counterpart to the human switch predicates above. Kept on
|
|
91
97
|
// its own semantic seam because `bot` is delegable but never human-switchable.
|
|
92
98
|
export { resolveAccountDelegationAccess } from './accountDelegationAccess';
|
|
93
99
|
export type {
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
AccountDelegationAccess,
|
|
101
|
+
AccountDelegationNode,
|
|
96
102
|
} from './accountDelegationAccess';
|
|
97
103
|
|
|
98
104
|
// Headless controller for the unified account dialog. Framework-agnostic
|
|
@@ -101,19 +107,19 @@ export type {
|
|
|
101
107
|
// Commons QR / same-device Commons identity). Reuses `SessionClient.switchAccount` /
|
|
102
108
|
// `oxy.accounts.actAs` for the uniform switch.
|
|
103
109
|
export {
|
|
104
|
-
|
|
105
|
-
|
|
110
|
+
AccountDialogController,
|
|
111
|
+
createAccountDialogController,
|
|
106
112
|
} from './accountDialogController';
|
|
107
113
|
export type {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
AccountDialogControllerOptions,
|
|
115
|
+
AccountDialogSnapshot,
|
|
116
|
+
AccountDialogView,
|
|
117
|
+
CommonsAvailability,
|
|
118
|
+
ContextChoiceOutcome,
|
|
119
|
+
SignInFailureReason,
|
|
120
|
+
SignInFlowPhase,
|
|
121
|
+
SignInFlowState,
|
|
122
|
+
SignInProgress,
|
|
117
123
|
} from './accountDialogController';
|
|
118
124
|
|
|
119
125
|
// ---------------------------------------------------------------------------
|
|
@@ -124,16 +130,16 @@ export type {
|
|
|
124
130
|
// via `POST /session/device/token`.
|
|
125
131
|
// ---------------------------------------------------------------------------
|
|
126
132
|
export {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
createWebAuthStateStore,
|
|
134
|
+
createNativeAuthStateStore,
|
|
135
|
+
createMemoryAuthStateStore,
|
|
136
|
+
AUTH_STATE_STORAGE_KEY,
|
|
131
137
|
} from './authStateStore';
|
|
132
138
|
export type {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
PersistedAuthState,
|
|
140
|
+
AuthStateStore,
|
|
141
|
+
AuthStateWriteGuard,
|
|
142
|
+
NativeKeyValueStorage,
|
|
137
143
|
} from './authStateStore';
|
|
138
144
|
|
|
139
145
|
// The shared NATIVE DeviceSession credential — how several official apps on one
|
|
@@ -142,22 +148,22 @@ export type {
|
|
|
142
148
|
// Commons private identity key: an app that only needs a session must never be
|
|
143
149
|
// handed the key that signs identity approvals.
|
|
144
150
|
export {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
+
createSharedMirroringAuthStateStore,
|
|
152
|
+
decideSharedDeviceJoin,
|
|
153
|
+
decideSharedDevicePublish,
|
|
154
|
+
normalizeSharedDeviceSessionRead,
|
|
155
|
+
publishProvenDeviceCredential,
|
|
156
|
+
readLocalDeviceCredential,
|
|
151
157
|
} from './sharedDeviceCredential';
|
|
152
158
|
export type {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
SharedDeviceCredential,
|
|
160
|
+
SharedDeviceCredentialRead,
|
|
161
|
+
SharedDeviceCredentialStore,
|
|
162
|
+
SharedDeviceJoinDecision,
|
|
163
|
+
SharedDeviceJoinSkipReason,
|
|
164
|
+
SharedDevicePublishDecision,
|
|
165
|
+
SharedDevicePublishOutcome,
|
|
166
|
+
SharedDevicePublishSkipReason,
|
|
161
167
|
} from './sharedDeviceCredential';
|
|
162
168
|
|
|
163
169
|
// Identity-bound sessions (the identity vault). The pin is the durable
|
|
@@ -165,47 +171,46 @@ export type {
|
|
|
165
171
|
// and the account it authenticates as; it is what keeps such a client from
|
|
166
172
|
// following the device's mutable `activeAccountId`.
|
|
167
173
|
export {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
174
|
+
createWebIdentityPinStore,
|
|
175
|
+
createNativeIdentityPinStore,
|
|
176
|
+
createMemoryIdentityPinStore,
|
|
177
|
+
identityPinMatches,
|
|
178
|
+
IDENTITY_PIN_STORAGE_KEY,
|
|
173
179
|
} from './identityPin';
|
|
174
180
|
export type { IdentityPin, IdentityPinStore } from './identityPin';
|
|
175
181
|
export {
|
|
176
|
-
|
|
177
|
-
|
|
182
|
+
resolveIdentityPin,
|
|
183
|
+
establishIdentitySession,
|
|
178
184
|
} from './identitySession';
|
|
179
185
|
export type {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
186
|
+
IdentityBinding,
|
|
187
|
+
IdentityRequestOptions,
|
|
188
|
+
EstablishedIdentitySession,
|
|
183
189
|
} from './identitySession';
|
|
184
190
|
export {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
+
refreshPersistedSession,
|
|
192
|
+
refreshDeviceSecretArm,
|
|
193
|
+
createAuthRefreshHandler,
|
|
194
|
+
installAuthRefreshHandler,
|
|
195
|
+
startTokenRefreshScheduler,
|
|
196
|
+
TOKEN_REFRESH_LEAD_MS,
|
|
191
197
|
} from './refresh';
|
|
192
198
|
export type { RefreshDeps, TokenRefreshSchedulerHandle, DeviceSecretMintOutcome } from './refresh';
|
|
193
199
|
|
|
194
200
|
export { runSessionColdBoot } from '../boot/sessionColdBoot';
|
|
195
201
|
export type {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
202
|
+
RunSessionColdBootOptions,
|
|
203
|
+
SessionMode,
|
|
204
|
+
SignedOutReason,
|
|
205
|
+
DeviceBootSession,
|
|
200
206
|
} from '../boot/sessionColdBoot';
|
|
201
207
|
|
|
202
208
|
export { runColdBoot } from '../utils/coldBoot';
|
|
203
209
|
export type {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
+
ColdBootStep,
|
|
211
|
+
ColdBootStepResult,
|
|
212
|
+
ColdBootSession,
|
|
213
|
+
ColdBootSkip,
|
|
214
|
+
ColdBootOutcome,
|
|
215
|
+
RunColdBootOptions,
|
|
210
216
|
} from '../utils/coldBoot';
|
|
211
|
-
|
package/src/session/refresh.ts
CHANGED
|
@@ -27,7 +27,11 @@ import type { AuthRefreshHandler, AuthRefreshReason } from '../HttpService';
|
|
|
27
27
|
import { matchesAuthState, type AuthStateStore, type PersistedAuthState } from './authStateStore';
|
|
28
28
|
import type { SharedDeviceCredentialStore } from './sharedDeviceCredential';
|
|
29
29
|
import type { IdentityPin } from './identityPin';
|
|
30
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
establishIdentitySession,
|
|
32
|
+
resolveIdentityPin,
|
|
33
|
+
type IdentityBinding,
|
|
34
|
+
} from './identitySession';
|
|
31
35
|
import { isNative } from '../utils/platform';
|
|
32
36
|
import { extractErrorStatus } from '../utils/errorUtils';
|
|
33
37
|
import { logger } from '../logger';
|
|
@@ -178,7 +182,7 @@ export async function refreshDeviceSecretArm(deps: {
|
|
|
178
182
|
const pin = deps.pin ?? null;
|
|
179
183
|
const isCurrent = deps.isCurrent ?? (() => true);
|
|
180
184
|
return oxy.http.runSingleFlightDeviceSecretMint(async () => {
|
|
181
|
-
if (!isCurrent()) return {status: 'session-ended'};
|
|
185
|
+
if (!isCurrent()) return { status: 'session-ended' };
|
|
182
186
|
const epoch = oxy.http.getSessionEpoch();
|
|
183
187
|
const persisted = await store.load();
|
|
184
188
|
if (!persisted?.deviceId || !persisted?.deviceSecret) {
|
|
@@ -227,19 +231,29 @@ export async function refreshDeviceSecretArm(deps: {
|
|
|
227
231
|
// push. Its exact live holder's authoritative empty-device rejection
|
|
228
232
|
// must suppress automatic key recovery on this and future boots.
|
|
229
233
|
// A late rejection for a replaced session/local epoch is not current.
|
|
230
|
-
if (
|
|
234
|
+
if (
|
|
235
|
+
pin === null &&
|
|
236
|
+
store.setAutomaticIdentitySignInSuppressed &&
|
|
237
|
+
(!invalidSecret || (persisted.sessionId && persisted.userId))
|
|
238
|
+
) {
|
|
231
239
|
const current = await store.load();
|
|
232
240
|
if (
|
|
233
|
-
!isCurrent() ||
|
|
241
|
+
!isCurrent() ||
|
|
242
|
+
oxy.http.getSessionEpoch() !== epoch ||
|
|
234
243
|
current?.deviceId !== persisted.deviceId ||
|
|
235
244
|
current.deviceSecret !== persisted.deviceSecret ||
|
|
236
245
|
current.sessionId !== persisted.sessionId ||
|
|
237
246
|
current.userId !== persisted.userId ||
|
|
238
247
|
current.accessToken !== persisted.accessToken
|
|
239
|
-
)
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
248
|
+
)
|
|
249
|
+
return { status: 'session-ended' };
|
|
250
|
+
if (
|
|
251
|
+
!(await store.setAutomaticIdentitySignInSuppressed(true, {
|
|
252
|
+
expectedState: persisted,
|
|
253
|
+
isCurrent: () => isCurrent() && oxy.http.getSessionEpoch() === epoch,
|
|
254
|
+
}))
|
|
255
|
+
)
|
|
256
|
+
return { status: 'session-ended' };
|
|
243
257
|
}
|
|
244
258
|
return { status: invalidSecret ? 'invalid-secret' : 'no-session' };
|
|
245
259
|
}
|
|
@@ -264,7 +278,7 @@ export async function refreshDeviceSecretArm(deps: {
|
|
|
264
278
|
expiresAt: mint.expiresAt,
|
|
265
279
|
...(bound ? { sessionId: bound.sessionId, userId: bound.accountId } : {}),
|
|
266
280
|
};
|
|
267
|
-
if (!isCurrent()) return {status: 'session-ended'};
|
|
281
|
+
if (!isCurrent()) return { status: 'session-ended' };
|
|
268
282
|
if (oxy.http.getSessionEpoch() !== epoch) {
|
|
269
283
|
// A logout or account/session switch invalidated this mint. Preserve
|
|
270
284
|
// only credential rotation for an otherwise unchanged retained context;
|
|
@@ -274,17 +288,23 @@ export async function refreshDeviceSecretArm(deps: {
|
|
|
274
288
|
const retainedEpoch = oxy.http.getSessionEpoch();
|
|
275
289
|
const current = await store.load();
|
|
276
290
|
if (store.saveIfCurrent && current && matchesAuthState(current, persisted)) {
|
|
277
|
-
await store.saveIfCurrent(
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
291
|
+
await store.saveIfCurrent(
|
|
292
|
+
{ ...current, deviceSecret: mint.nextDeviceSecret },
|
|
293
|
+
{
|
|
294
|
+
expectedState: current,
|
|
295
|
+
isCurrent: () => isCurrent() && oxy.http.getSessionEpoch() === retainedEpoch,
|
|
296
|
+
},
|
|
297
|
+
);
|
|
281
298
|
}
|
|
282
299
|
return { status: 'session-ended' };
|
|
283
300
|
}
|
|
284
301
|
// Persist nextDeviceSecret (read-back-verified) BEFORE planting the token.
|
|
285
302
|
// A failed durable persist must NOT plant.
|
|
286
303
|
const persistedOk = store.saveIfCurrent
|
|
287
|
-
? await store.saveIfCurrent(next, {
|
|
304
|
+
? await store.saveIfCurrent(next, {
|
|
305
|
+
expectedState: persisted,
|
|
306
|
+
isCurrent: () => isCurrent() && oxy.http.getSessionEpoch() === epoch,
|
|
307
|
+
})
|
|
288
308
|
: await store.save(next);
|
|
289
309
|
if (!persistedOk) {
|
|
290
310
|
return { status: 'persist-failed' };
|
|
@@ -320,41 +340,72 @@ export async function refreshSharedDeviceArm(deps: {
|
|
|
320
340
|
const isCurrent = deps.isCurrent ?? (() => true);
|
|
321
341
|
return oxy.http.runSingleFlightDeviceSecretMint(async () => {
|
|
322
342
|
const epoch = oxy.http.getSessionEpoch();
|
|
323
|
-
if (!isCurrent()) return {status: 'session-ended'};
|
|
343
|
+
if (!isCurrent()) return { status: 'session-ended' };
|
|
324
344
|
const before = await store.load();
|
|
325
|
-
if (before?.deviceId && before.deviceSecret && !deps.rejectedLocalHolder)
|
|
345
|
+
if (before?.deviceId && before.deviceSecret && !deps.rejectedLocalHolder)
|
|
346
|
+
return { status: 'no-secret' };
|
|
326
347
|
const read = await shared.read();
|
|
327
348
|
if (read.state !== 'present' || !store.saveIfCurrent) return { status: 'no-secret' };
|
|
328
349
|
const credential = read.credential;
|
|
329
|
-
if (credential.deviceId === before?.deviceId && credential.deviceSecret === before.deviceSecret)
|
|
350
|
+
if (credential.deviceId === before?.deviceId && credential.deviceSecret === before.deviceSecret)
|
|
351
|
+
return { status: 'no-secret' };
|
|
330
352
|
let mint: DeviceTokenMintResponse;
|
|
331
353
|
try {
|
|
332
354
|
mint = await oxy.devices.mintToken(credential.deviceId, credential.deviceSecret);
|
|
333
355
|
} catch (error) {
|
|
334
356
|
if (extractErrorStatus(error) === 429) oxy.http.noteRefreshRateLimited();
|
|
335
357
|
if (extractErrorStatus(error) === 401) {
|
|
336
|
-
const message = (error as {message?: unknown})?.message;
|
|
358
|
+
const message = (error as { message?: unknown })?.message;
|
|
337
359
|
if (typeof message === 'string' && message.includes('invalid_device_secret')) {
|
|
338
360
|
// There is no cross-app CAS clear in the bridge contract. An old
|
|
339
361
|
// rejection cannot delete a slot another app has since published.
|
|
340
|
-
return {status: 'invalid-secret'};
|
|
362
|
+
return { status: 'invalid-secret' };
|
|
341
363
|
}
|
|
342
|
-
if (typeof message === 'string' && message.includes('no_active_session'))
|
|
364
|
+
if (typeof message === 'string' && message.includes('no_active_session'))
|
|
365
|
+
return { status: 'no-session' };
|
|
343
366
|
}
|
|
344
|
-
return {status: 'transient'};
|
|
367
|
+
return { status: 'transient' };
|
|
345
368
|
}
|
|
346
|
-
const bound = mint.state.accounts.find(
|
|
347
|
-
|
|
348
|
-
|
|
369
|
+
const bound = mint.state.accounts.find(
|
|
370
|
+
(account) => account.accountId === mint.state.activeAccountId,
|
|
371
|
+
);
|
|
372
|
+
if (
|
|
373
|
+
!bound ||
|
|
374
|
+
mint.state.deviceId !== credential.deviceId ||
|
|
375
|
+
!mint.accessToken ||
|
|
376
|
+
!mint.nextDeviceSecret
|
|
377
|
+
)
|
|
378
|
+
return { status: 'transient' };
|
|
379
|
+
if (
|
|
380
|
+
!isCurrent() ||
|
|
381
|
+
oxy.http.getSessionEpoch() !== epoch ||
|
|
382
|
+
!matchesAuthState(await store.load(), before)
|
|
383
|
+
)
|
|
384
|
+
return { status: 'session-ended' };
|
|
349
385
|
const next: PersistedAuthState = {
|
|
350
|
-
deviceId: mint.state.deviceId,
|
|
351
|
-
|
|
352
|
-
|
|
386
|
+
deviceId: mint.state.deviceId,
|
|
387
|
+
deviceSecret: mint.nextDeviceSecret,
|
|
388
|
+
sessionId: bound.sessionId,
|
|
389
|
+
userId: bound.accountId,
|
|
390
|
+
accessToken: mint.accessToken,
|
|
391
|
+
expiresAt: mint.expiresAt,
|
|
353
392
|
};
|
|
354
|
-
if (
|
|
355
|
-
|
|
393
|
+
if (
|
|
394
|
+
!(await store.saveIfCurrent(next, {
|
|
395
|
+
expectedState: before,
|
|
396
|
+
isCurrent: () => isCurrent() && oxy.http.getSessionEpoch() === epoch,
|
|
397
|
+
}))
|
|
398
|
+
)
|
|
399
|
+
return { status: 'persist-failed' };
|
|
400
|
+
if (!isCurrent() || oxy.http.getSessionEpoch() !== epoch) return { status: 'session-ended' };
|
|
356
401
|
oxy.session.setAccessToken(mint.accessToken);
|
|
357
|
-
return {
|
|
402
|
+
return {
|
|
403
|
+
status: 'ok',
|
|
404
|
+
token: mint.accessToken,
|
|
405
|
+
sessionId: bound.sessionId,
|
|
406
|
+
userId: bound.accountId,
|
|
407
|
+
state: mint.state,
|
|
408
|
+
};
|
|
358
409
|
});
|
|
359
410
|
}
|
|
360
411
|
|
|
@@ -388,7 +439,10 @@ export async function refreshPersistedSession(deps: RefreshDeps): Promise<string
|
|
|
388
439
|
if (deps.isCurrent && !deps.isCurrent()) return null;
|
|
389
440
|
const identity = deps.identity ?? null;
|
|
390
441
|
// The shared identity is never an identity-bound client's recovery path.
|
|
391
|
-
const allowCommonsIdentityFallback = identity
|
|
442
|
+
const allowCommonsIdentityFallback = identity
|
|
443
|
+
? false
|
|
444
|
+
: (deps.allowCommonsIdentityFallback ?? isNative()) &&
|
|
445
|
+
!(await store.isAutomaticIdentitySignInSuppressed?.());
|
|
392
446
|
const epoch = oxy.http.getSessionEpoch();
|
|
393
447
|
// Resolved per call: a re-established identity session can move the pin, and a
|
|
394
448
|
// replaced/removed local key clears it (in which case arm 1 must NOT mint —
|
|
@@ -405,10 +459,10 @@ export async function refreshPersistedSession(deps: RefreshDeps): Promise<string
|
|
|
405
459
|
case 'session-ended':
|
|
406
460
|
return null;
|
|
407
461
|
case 'transient':
|
|
408
|
-
logger.debug(
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
);
|
|
462
|
+
logger.debug('Persisted deviceSecret mint failed (transient) — keeping store', {
|
|
463
|
+
component: 'refresh',
|
|
464
|
+
method: 'refreshPersistedSession',
|
|
465
|
+
});
|
|
412
466
|
return null;
|
|
413
467
|
case 'persist-failed':
|
|
414
468
|
// The server rotated the secret but it did not durably persist. Do NOT fall
|
|
@@ -424,11 +478,22 @@ export async function refreshPersistedSession(deps: RefreshDeps): Promise<string
|
|
|
424
478
|
case 'invalid-secret':
|
|
425
479
|
case 'no-session': {
|
|
426
480
|
if (!identity && deps.sharedDeviceCredential) {
|
|
427
|
-
const joined = await refreshSharedDeviceArm({
|
|
481
|
+
const joined = await refreshSharedDeviceArm({
|
|
482
|
+
oxy,
|
|
483
|
+
store,
|
|
484
|
+
shared: deps.sharedDeviceCredential,
|
|
485
|
+
rejectedLocalHolder: true,
|
|
486
|
+
isCurrent: deps.isCurrent,
|
|
487
|
+
});
|
|
428
488
|
if (joined.status === 'ok') return joined.token;
|
|
429
489
|
if (joined.status === 'session-ended' || joined.status === 'persist-failed') return null;
|
|
430
490
|
}
|
|
431
|
-
if (
|
|
491
|
+
if (
|
|
492
|
+
!identity &&
|
|
493
|
+
arm1.status === 'invalid-secret' &&
|
|
494
|
+
(await store.isAutomaticIdentitySignInSuppressed?.())
|
|
495
|
+
)
|
|
496
|
+
return null;
|
|
432
497
|
if (arm1.status === 'no-session' && !identity) {
|
|
433
498
|
if (store.setAutomaticIdentitySignInSuppressed) return null;
|
|
434
499
|
// The holder is still valid, but its account session ended. Retain only
|
|
@@ -436,7 +501,12 @@ export async function refreshPersistedSession(deps: RefreshDeps): Promise<string
|
|
|
436
501
|
// to turn this signed-out verdict into a new account session.
|
|
437
502
|
const persisted = await store.load();
|
|
438
503
|
if (persisted?.deviceId && persisted.deviceSecret) {
|
|
439
|
-
await store.save({
|
|
504
|
+
await store.save({
|
|
505
|
+
sessionId: '',
|
|
506
|
+
userId: '',
|
|
507
|
+
deviceId: persisted.deviceId,
|
|
508
|
+
deviceSecret: persisted.deviceSecret,
|
|
509
|
+
});
|
|
440
510
|
}
|
|
441
511
|
return null;
|
|
442
512
|
}
|
|
@@ -465,9 +535,19 @@ export async function refreshPersistedSession(deps: RefreshDeps): Promise<string
|
|
|
465
535
|
break;
|
|
466
536
|
case 'no-secret':
|
|
467
537
|
if (!identity && deps.sharedDeviceCredential) {
|
|
468
|
-
const joined = await refreshSharedDeviceArm({
|
|
538
|
+
const joined = await refreshSharedDeviceArm({
|
|
539
|
+
oxy,
|
|
540
|
+
store,
|
|
541
|
+
shared: deps.sharedDeviceCredential,
|
|
542
|
+
isCurrent: deps.isCurrent,
|
|
543
|
+
});
|
|
469
544
|
if (joined.status === 'ok') return joined.token;
|
|
470
|
-
if (
|
|
545
|
+
if (
|
|
546
|
+
joined.status === 'session-ended' ||
|
|
547
|
+
joined.status === 'persist-failed' ||
|
|
548
|
+
joined.status === 'transient'
|
|
549
|
+
)
|
|
550
|
+
return null;
|
|
471
551
|
}
|
|
472
552
|
break;
|
|
473
553
|
}
|
|
@@ -478,14 +558,23 @@ export async function refreshPersistedSession(deps: RefreshDeps): Promise<string
|
|
|
478
558
|
|
|
479
559
|
// Never after a sign-out: the shared identity is a KEY, not a session, and
|
|
480
560
|
// proving it here would sign the user straight back in.
|
|
481
|
-
if (
|
|
561
|
+
if (
|
|
562
|
+
allowCommonsIdentityFallback &&
|
|
563
|
+
(deps.isCurrent?.() ?? true) &&
|
|
564
|
+
!oxy.http.hasSessionEnded() &&
|
|
565
|
+
!(await store.isAutomaticIdentitySignInSuppressed?.())
|
|
566
|
+
) {
|
|
482
567
|
try {
|
|
483
568
|
// Planted here, not by the sign-in: a sign-out that lands while the
|
|
484
569
|
// challenge round-trips must win, or the identity proof signs the user
|
|
485
570
|
// straight back in.
|
|
486
571
|
const session = await oxy.auth.signInWithCommonsIdentity({ plantTokens: false });
|
|
487
572
|
if (session?.accessToken) {
|
|
488
|
-
if (
|
|
573
|
+
if (
|
|
574
|
+
!(deps.isCurrent?.() ?? true) ||
|
|
575
|
+
oxy.http.getSessionEpoch() !== epoch ||
|
|
576
|
+
(await store.isAutomaticIdentitySignInSuppressed?.())
|
|
577
|
+
) {
|
|
489
578
|
return null;
|
|
490
579
|
}
|
|
491
580
|
// Repopulate the fast device-secret lane from the identity re-mint.
|
|
@@ -499,7 +588,11 @@ export async function refreshPersistedSession(deps: RefreshDeps): Promise<string
|
|
|
499
588
|
expiresAt: session.expiresAt,
|
|
500
589
|
});
|
|
501
590
|
}
|
|
502
|
-
if (
|
|
591
|
+
if (
|
|
592
|
+
!(deps.isCurrent?.() ?? true) ||
|
|
593
|
+
oxy.http.getSessionEpoch() !== epoch ||
|
|
594
|
+
(await store.isAutomaticIdentitySignInSuppressed?.())
|
|
595
|
+
) {
|
|
503
596
|
return null;
|
|
504
597
|
}
|
|
505
598
|
oxy.session.setAccessToken(session.accessToken);
|
|
@@ -644,7 +737,8 @@ export function startTokenRefreshScheduler(oxy: OxyServices): TokenRefreshSchedu
|
|
|
644
737
|
scheduleFromExpiry();
|
|
645
738
|
return;
|
|
646
739
|
}
|
|
647
|
-
void oxy.http
|
|
740
|
+
void oxy.http
|
|
741
|
+
.refreshAccessToken('preflight')
|
|
648
742
|
.then((token) => Boolean(token))
|
|
649
743
|
.catch(() => false)
|
|
650
744
|
.then((ok) => {
|
|
@@ -13,9 +13,7 @@ import type { DeviceCredential, SessionClientHost } from './SessionClient';
|
|
|
13
13
|
* platform-agnostic: every method it calls exists identically on
|
|
14
14
|
* `OxyServices` regardless of host (web, Expo/RN, Node).
|
|
15
15
|
*/
|
|
16
|
-
export function createSessionClientHost(
|
|
17
|
-
oxyServices: OxyServices,
|
|
18
|
-
): SessionClientHost & {
|
|
16
|
+
export function createSessionClientHost(oxyServices: OxyServices): SessionClientHost & {
|
|
19
17
|
setCurrentAccountId(id: string | null): void;
|
|
20
18
|
setDeviceCredential(credential: DeviceCredential | null): void;
|
|
21
19
|
} {
|