@oxyhq/core 2.4.0 → 3.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.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/OxyServices.js +1 -1
- package/dist/cjs/mixins/OxyServices.applications.js +212 -0
- package/dist/cjs/mixins/OxyServices.auth.js +4 -4
- package/dist/cjs/mixins/OxyServices.fedcm.js +52 -2
- package/dist/cjs/mixins/index.js +2 -2
- package/dist/cjs/utils/coldBoot.js +66 -17
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/OxyServices.js +1 -1
- package/dist/esm/mixins/OxyServices.applications.js +209 -0
- package/dist/esm/mixins/OxyServices.auth.js +4 -4
- package/dist/esm/mixins/OxyServices.fedcm.js +52 -2
- package/dist/esm/mixins/index.js +2 -2
- package/dist/esm/utils/coldBoot.js +66 -17
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/OxyServices.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/mixins/OxyServices.applications.d.ts +317 -0
- package/dist/types/mixins/OxyServices.auth.d.ts +4 -4
- package/dist/types/mixins/OxyServices.fedcm.d.ts +1 -0
- package/dist/types/mixins/OxyServices.utility.d.ts +1 -1
- package/dist/types/mixins/index.d.ts +2 -2
- package/dist/types/utils/coldBoot.d.ts +26 -0
- package/package.json +1 -1
- package/src/OxyServices.ts +1 -1
- package/src/index.ts +29 -0
- package/src/mixins/OxyServices.applications.ts +511 -0
- package/src/mixins/OxyServices.auth.ts +4 -4
- package/src/mixins/OxyServices.fedcm.ts +56 -2
- package/src/mixins/OxyServices.utility.ts +1 -1
- package/src/mixins/__tests__/fedcm.test.ts +52 -0
- package/src/mixins/index.ts +3 -3
- package/src/utils/__tests__/coldBoot.test.ts +150 -0
- package/src/utils/coldBoot.ts +96 -17
- package/src/mixins/OxyServices.developer.ts +0 -114
|
@@ -82,7 +82,7 @@ import { composeOxyServices } from './mixins';
|
|
|
82
82
|
* - **Payment**: Payment processing
|
|
83
83
|
* - **Karma**: Karma system
|
|
84
84
|
* - **Assets**: File upload and asset management
|
|
85
|
-
* - **
|
|
85
|
+
* - **Applications**: Application, membership, and credential management
|
|
86
86
|
* - **Location**: Location-based features
|
|
87
87
|
* - **Analytics**: Analytics tracking
|
|
88
88
|
* - **Devices**: Device management
|
package/dist/types/index.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export type { ServiceApp, ServiceActingAsVerification } from './mixins/OxyServic
|
|
|
33
33
|
export type { CreateManagedAccountInput, ManagedAccountManager, ManagedAccount, } from './mixins/OxyServices.managedAccounts';
|
|
34
34
|
export type { ContactDiscoveryMatch, ContactDiscoveryResponse, } from './mixins/OxyServices.contacts';
|
|
35
35
|
export { OxyAppDataIdentifierError } from './mixins/OxyServices.appData';
|
|
36
|
+
export type { Application, ApplicationMember, ApplicationCredential, ApplicationRole, ApplicationType, ApplicationStatus, ApplicationMemberStatus, ApplicationCredentialType, ApplicationCredentialStatus, ApplicationEnvironment, CreateApplicationInput, UpdateApplicationInput, InviteApplicationMemberInput, UpdateApplicationMemberInput, TransferApplicationOwnershipInput, CreateApplicationCredentialInput, ApplicationCredentialWithSecret, ApplicationUsagePeriod, ApplicationUsageSummary, ApplicationUsageByDay, ApplicationUsageByEndpoint, ApplicationUsageStats, ApplicationSuccessResult, } from './mixins/OxyServices.applications';
|
|
36
37
|
export { SessionSyncRequiredError, AuthenticationFailedError, ensureValidToken, isAuthenticationError, withAuthErrorHandling, authenticatedApiCall, } from './utils/authHelpers';
|
|
37
38
|
export type { HandleApiErrorOptions } from './utils/authHelpers';
|
|
38
39
|
export { mergeSessions, normalizeAndSortSessions, sessionsArraysEqual, } from './utils/sessionUtils';
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Applications Methods Mixin
|
|
3
|
+
*
|
|
4
|
+
* Provides methods for managing Oxy applications, their members, and their
|
|
5
|
+
* credentials via the `/applications` API. An application is a multi-user
|
|
6
|
+
* entity: membership (with a role) grants permissions; credentials
|
|
7
|
+
* (public/confidential/service) carry OAuth client identifiers and the
|
|
8
|
+
* service-token API key material.
|
|
9
|
+
*
|
|
10
|
+
* Reference applications by their Mongo `_id` (`applicationId`) and credentials
|
|
11
|
+
* by their `credentialId`. Never by name.
|
|
12
|
+
*/
|
|
13
|
+
import type { OxyServicesBase } from '../OxyServices.base';
|
|
14
|
+
/**
|
|
15
|
+
* Application classification. Set only by Oxy platform staff — never editable
|
|
16
|
+
* through the normal member-facing update path.
|
|
17
|
+
*/
|
|
18
|
+
export type ApplicationType = 'first_party' | 'third_party' | 'internal' | 'system';
|
|
19
|
+
/** Lifecycle status of an application. */
|
|
20
|
+
export type ApplicationStatus = 'active' | 'suspended' | 'deleted' | 'pending_review';
|
|
21
|
+
/** Role a member holds within an application. */
|
|
22
|
+
export type ApplicationRole = 'owner' | 'admin' | 'developer' | 'viewer' | 'billing';
|
|
23
|
+
/** Membership lifecycle status. */
|
|
24
|
+
export type ApplicationMemberStatus = 'active' | 'invited' | 'removed';
|
|
25
|
+
/** Credential kind. `service` credentials mint service tokens. */
|
|
26
|
+
export type ApplicationCredentialType = 'public' | 'confidential' | 'service';
|
|
27
|
+
/** Deployment environment a credential is scoped to. */
|
|
28
|
+
export type ApplicationEnvironment = 'development' | 'staging' | 'production';
|
|
29
|
+
/** Credential lifecycle status. */
|
|
30
|
+
export type ApplicationCredentialStatus = 'active' | 'deprecated' | 'revoked';
|
|
31
|
+
/**
|
|
32
|
+
* Client-facing Application shape returned by the `/applications` API.
|
|
33
|
+
* Mirrors the server `Application` model with `_id` as a string and dates
|
|
34
|
+
* serialized to ISO strings.
|
|
35
|
+
*/
|
|
36
|
+
export interface Application {
|
|
37
|
+
_id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
websiteUrl?: string;
|
|
41
|
+
icon?: string;
|
|
42
|
+
type: ApplicationType;
|
|
43
|
+
status: ApplicationStatus;
|
|
44
|
+
isOfficial: boolean;
|
|
45
|
+
isInternal: boolean;
|
|
46
|
+
capabilities: string[];
|
|
47
|
+
redirectUris: string[];
|
|
48
|
+
scopes: string[];
|
|
49
|
+
webhookUrl?: string;
|
|
50
|
+
devWebhookUrl?: string;
|
|
51
|
+
createdByUserId: string;
|
|
52
|
+
createdAt: string;
|
|
53
|
+
updatedAt: string;
|
|
54
|
+
/**
|
|
55
|
+
* The calling user's own membership in this application, embedded by the API
|
|
56
|
+
* on list (`GET /applications`) and detail (`GET /applications/:appId`)
|
|
57
|
+
* responses. Use `callerMembership.permissions` to gate UI affordances.
|
|
58
|
+
*/
|
|
59
|
+
callerMembership?: ApplicationMember;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Client-facing ApplicationMember shape. `permissions` is derived from `role`
|
|
63
|
+
* on the server at write time.
|
|
64
|
+
*/
|
|
65
|
+
export interface ApplicationMember {
|
|
66
|
+
_id: string;
|
|
67
|
+
applicationId: string;
|
|
68
|
+
userId: string;
|
|
69
|
+
role: ApplicationRole;
|
|
70
|
+
permissions: string[];
|
|
71
|
+
invitedByUserId?: string;
|
|
72
|
+
joinedAt?: string;
|
|
73
|
+
status: ApplicationMemberStatus;
|
|
74
|
+
createdAt: string;
|
|
75
|
+
updatedAt: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Client-facing ApplicationCredential shape. The raw secret is NEVER part of
|
|
79
|
+
* this shape — it is returned exactly once, separately, at creation/rotation.
|
|
80
|
+
*/
|
|
81
|
+
export interface ApplicationCredential {
|
|
82
|
+
_id: string;
|
|
83
|
+
applicationId: string;
|
|
84
|
+
name: string;
|
|
85
|
+
publicKey: string;
|
|
86
|
+
type: ApplicationCredentialType;
|
|
87
|
+
environment: ApplicationEnvironment;
|
|
88
|
+
scopes: string[];
|
|
89
|
+
status: ApplicationCredentialStatus;
|
|
90
|
+
lastUsedAt?: string;
|
|
91
|
+
expiresAt?: string;
|
|
92
|
+
createdByUserId: string;
|
|
93
|
+
createdAt: string;
|
|
94
|
+
updatedAt: string;
|
|
95
|
+
}
|
|
96
|
+
/** Input accepted by `createApplication`. Staff-only fields are not settable here. */
|
|
97
|
+
export interface CreateApplicationInput {
|
|
98
|
+
name: string;
|
|
99
|
+
description?: string;
|
|
100
|
+
websiteUrl?: string;
|
|
101
|
+
icon?: string;
|
|
102
|
+
redirectUris?: string[];
|
|
103
|
+
scopes?: string[];
|
|
104
|
+
}
|
|
105
|
+
/** Input accepted by `updateApplication`. Staff-only fields are not settable here. */
|
|
106
|
+
export interface UpdateApplicationInput {
|
|
107
|
+
name?: string;
|
|
108
|
+
description?: string;
|
|
109
|
+
websiteUrl?: string;
|
|
110
|
+
icon?: string;
|
|
111
|
+
redirectUris?: string[];
|
|
112
|
+
scopes?: string[];
|
|
113
|
+
webhookUrl?: string;
|
|
114
|
+
devWebhookUrl?: string;
|
|
115
|
+
status?: ApplicationStatus;
|
|
116
|
+
}
|
|
117
|
+
/** Input accepted by `inviteApplicationMember`. The owner role cannot be invited. */
|
|
118
|
+
export interface InviteApplicationMemberInput {
|
|
119
|
+
userId: string;
|
|
120
|
+
role: Exclude<ApplicationRole, 'owner'>;
|
|
121
|
+
}
|
|
122
|
+
/** Input accepted by `updateApplicationMember`. */
|
|
123
|
+
export interface UpdateApplicationMemberInput {
|
|
124
|
+
role: ApplicationRole;
|
|
125
|
+
}
|
|
126
|
+
/** Input accepted by `transferApplicationOwnership`. */
|
|
127
|
+
export interface TransferApplicationOwnershipInput {
|
|
128
|
+
userId: string;
|
|
129
|
+
}
|
|
130
|
+
/** Input accepted by `createApplicationCredential`. */
|
|
131
|
+
export interface CreateApplicationCredentialInput {
|
|
132
|
+
name: string;
|
|
133
|
+
type: ApplicationCredentialType;
|
|
134
|
+
environment: ApplicationEnvironment;
|
|
135
|
+
scopes?: string[];
|
|
136
|
+
}
|
|
137
|
+
/** Result of creating or rotating a credential — `secret` is returned ONCE. */
|
|
138
|
+
export interface ApplicationCredentialWithSecret {
|
|
139
|
+
credential: ApplicationCredential;
|
|
140
|
+
secret: string;
|
|
141
|
+
}
|
|
142
|
+
/** Time window for application usage statistics. */
|
|
143
|
+
export type ApplicationUsagePeriod = '24h' | '7d' | '30d' | '90d';
|
|
144
|
+
/** Aggregate totals for an application over the requested period. */
|
|
145
|
+
export interface ApplicationUsageSummary {
|
|
146
|
+
totalRequests: number;
|
|
147
|
+
totalTokens: number;
|
|
148
|
+
totalCredits: number;
|
|
149
|
+
avgResponseTime: number;
|
|
150
|
+
successfulRequests: number;
|
|
151
|
+
errorRequests: number;
|
|
152
|
+
}
|
|
153
|
+
/** Per-day usage bucket. `_id` is the day key (e.g. `YYYY-MM-DD`). */
|
|
154
|
+
export interface ApplicationUsageByDay {
|
|
155
|
+
_id: string;
|
|
156
|
+
requests: number;
|
|
157
|
+
tokens: number;
|
|
158
|
+
credits: number;
|
|
159
|
+
}
|
|
160
|
+
/** Per-endpoint usage bucket. `_id` is the endpoint identifier. */
|
|
161
|
+
export interface ApplicationUsageByEndpoint {
|
|
162
|
+
_id: string;
|
|
163
|
+
requests: number;
|
|
164
|
+
tokens: number;
|
|
165
|
+
}
|
|
166
|
+
/** Usage statistics for an application over a period. */
|
|
167
|
+
export interface ApplicationUsageStats {
|
|
168
|
+
summary: ApplicationUsageSummary;
|
|
169
|
+
byDay: ApplicationUsageByDay[];
|
|
170
|
+
byEndpoint: ApplicationUsageByEndpoint[];
|
|
171
|
+
}
|
|
172
|
+
/** Result of a delete/remove/revoke/transfer operation. */
|
|
173
|
+
export interface ApplicationSuccessResult {
|
|
174
|
+
success: boolean;
|
|
175
|
+
}
|
|
176
|
+
export declare function OxyServicesApplicationsMixin<T extends typeof OxyServicesBase>(Base: T): {
|
|
177
|
+
new (...args: any[]): {
|
|
178
|
+
/**
|
|
179
|
+
* List applications the current user is an active member of.
|
|
180
|
+
*/
|
|
181
|
+
getApplications(): Promise<Application[]>;
|
|
182
|
+
/**
|
|
183
|
+
* Create a new application. The caller becomes its `owner`.
|
|
184
|
+
* @param data - Application configuration. Staff-only fields are ignored.
|
|
185
|
+
*/
|
|
186
|
+
createApplication(data: CreateApplicationInput): Promise<Application>;
|
|
187
|
+
/**
|
|
188
|
+
* Fetch a single application by id.
|
|
189
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
190
|
+
*/
|
|
191
|
+
getApplication(applicationId: string): Promise<Application>;
|
|
192
|
+
/**
|
|
193
|
+
* Update an application's mutable fields.
|
|
194
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
195
|
+
* @param data - Subset of updatable fields. Staff-only fields are ignored.
|
|
196
|
+
*/
|
|
197
|
+
updateApplication(applicationId: string, data: UpdateApplicationInput): Promise<Application>;
|
|
198
|
+
/**
|
|
199
|
+
* Soft-delete an application (owner only).
|
|
200
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
201
|
+
*/
|
|
202
|
+
deleteApplication(applicationId: string): Promise<ApplicationSuccessResult>;
|
|
203
|
+
/**
|
|
204
|
+
* List members of an application.
|
|
205
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
206
|
+
*/
|
|
207
|
+
getApplicationMembers(applicationId: string): Promise<ApplicationMember[]>;
|
|
208
|
+
/**
|
|
209
|
+
* Add a member to an application.
|
|
210
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
211
|
+
* @param data - Target user id and role (never `owner`).
|
|
212
|
+
*/
|
|
213
|
+
inviteApplicationMember(applicationId: string, data: InviteApplicationMemberInput): Promise<ApplicationMember>;
|
|
214
|
+
/**
|
|
215
|
+
* Change a member's role.
|
|
216
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
217
|
+
* @param memberId - The member's Mongo `_id`.
|
|
218
|
+
* @param data - New role.
|
|
219
|
+
*/
|
|
220
|
+
updateApplicationMember(applicationId: string, memberId: string, data: UpdateApplicationMemberInput): Promise<ApplicationMember>;
|
|
221
|
+
/**
|
|
222
|
+
* Remove a member from an application.
|
|
223
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
224
|
+
* @param memberId - The member's Mongo `_id`.
|
|
225
|
+
*/
|
|
226
|
+
removeApplicationMember(applicationId: string, memberId: string): Promise<ApplicationSuccessResult>;
|
|
227
|
+
/**
|
|
228
|
+
* Transfer ownership of an application to another member (owner only).
|
|
229
|
+
* Demotes the current owner to `admin` and promotes the target to `owner`.
|
|
230
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
231
|
+
* @param data - Target user id.
|
|
232
|
+
*/
|
|
233
|
+
transferApplicationOwnership(applicationId: string, data: TransferApplicationOwnershipInput): Promise<ApplicationSuccessResult>;
|
|
234
|
+
/**
|
|
235
|
+
* List an application's credentials. The response NEVER includes secrets.
|
|
236
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
237
|
+
*/
|
|
238
|
+
getApplicationCredentials(applicationId: string): Promise<ApplicationCredential[]>;
|
|
239
|
+
/**
|
|
240
|
+
* Create a credential. The plaintext `secret` is returned exactly ONCE;
|
|
241
|
+
* the server stores only a hash and will never return it again.
|
|
242
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
243
|
+
* @param data - Credential configuration.
|
|
244
|
+
*/
|
|
245
|
+
createApplicationCredential(applicationId: string, data: CreateApplicationCredentialInput): Promise<ApplicationCredentialWithSecret>;
|
|
246
|
+
/**
|
|
247
|
+
* Rotate a credential's secret. The new plaintext `secret` is returned
|
|
248
|
+
* exactly ONCE.
|
|
249
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
250
|
+
* @param credentialId - The credential's Mongo `_id`.
|
|
251
|
+
*/
|
|
252
|
+
rotateApplicationCredential(applicationId: string, credentialId: string): Promise<ApplicationCredentialWithSecret>;
|
|
253
|
+
/**
|
|
254
|
+
* Revoke a credential (`status='revoked'`). Revoked credentials can no
|
|
255
|
+
* longer authenticate.
|
|
256
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
257
|
+
* @param credentialId - The credential's Mongo `_id`.
|
|
258
|
+
*/
|
|
259
|
+
revokeApplicationCredential(applicationId: string, credentialId: string): Promise<ApplicationSuccessResult>;
|
|
260
|
+
/**
|
|
261
|
+
* Fetch usage statistics for an application.
|
|
262
|
+
* @param applicationId - The application's Mongo `_id`.
|
|
263
|
+
* @param period - Time window (defaults to the server default).
|
|
264
|
+
*/
|
|
265
|
+
getApplicationUsage(applicationId: string, period?: ApplicationUsagePeriod): Promise<ApplicationUsageStats>;
|
|
266
|
+
httpService: import("../HttpService").HttpService;
|
|
267
|
+
cloudURL: string;
|
|
268
|
+
config: import("../OxyServices.base").OxyConfig;
|
|
269
|
+
__resetTokensForTests(): void;
|
|
270
|
+
makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
|
|
271
|
+
getBaseURL(): string;
|
|
272
|
+
getSessionBaseUrl(): string;
|
|
273
|
+
getClient(): import("../HttpService").HttpService;
|
|
274
|
+
getMetrics(): {
|
|
275
|
+
totalRequests: number;
|
|
276
|
+
successfulRequests: number;
|
|
277
|
+
failedRequests: number;
|
|
278
|
+
cacheHits: number;
|
|
279
|
+
cacheMisses: number;
|
|
280
|
+
averageResponseTime: number;
|
|
281
|
+
};
|
|
282
|
+
clearCache(): void;
|
|
283
|
+
clearCacheEntry(key: string): void;
|
|
284
|
+
clearCacheByPrefix(prefix: string): number;
|
|
285
|
+
getCacheStats(): {
|
|
286
|
+
size: number;
|
|
287
|
+
hits: number;
|
|
288
|
+
misses: number;
|
|
289
|
+
hitRate: number;
|
|
290
|
+
};
|
|
291
|
+
getCloudURL(): string;
|
|
292
|
+
setTokens(accessToken: string, refreshToken?: string): void;
|
|
293
|
+
clearTokens(): void;
|
|
294
|
+
onTokensChanged(listener: (accessToken: string | null) => void): () => void;
|
|
295
|
+
_cachedUserId: string | null | undefined;
|
|
296
|
+
_cachedAccessToken: string | null;
|
|
297
|
+
getCurrentUserId(): string | null;
|
|
298
|
+
hasValidToken(): boolean;
|
|
299
|
+
getAccessToken(): string | null;
|
|
300
|
+
setActingAs(userId: string | null): void;
|
|
301
|
+
getActingAs(): string | null;
|
|
302
|
+
waitForAuth(timeoutMs?: number): Promise<boolean>;
|
|
303
|
+
withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
|
|
304
|
+
maxRetries?: number;
|
|
305
|
+
retryDelay?: number;
|
|
306
|
+
authTimeoutMs?: number;
|
|
307
|
+
}): Promise<T_1>;
|
|
308
|
+
validate(): Promise<boolean>;
|
|
309
|
+
handleError(error: unknown): Error;
|
|
310
|
+
healthCheck(): Promise<{
|
|
311
|
+
status: string;
|
|
312
|
+
users?: number;
|
|
313
|
+
timestamp?: string;
|
|
314
|
+
[key: string]: any;
|
|
315
|
+
}>;
|
|
316
|
+
};
|
|
317
|
+
} & T;
|
|
@@ -127,8 +127,8 @@ export declare function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(B
|
|
|
127
127
|
* legitimate multi-tenant hosts that need to switch credentials cannot leak
|
|
128
128
|
* one tenant's token to another tenant on the same instance.
|
|
129
129
|
*
|
|
130
|
-
* @param apiKey -
|
|
131
|
-
* @param apiSecret -
|
|
130
|
+
* @param apiKey - Application credential public key (oxy_dk_*)
|
|
131
|
+
* @param apiSecret - Application credential secret
|
|
132
132
|
*/
|
|
133
133
|
configureServiceAuth(apiKey: string, apiSecret: string): void;
|
|
134
134
|
/**
|
|
@@ -147,8 +147,8 @@ export declare function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(B
|
|
|
147
147
|
* This prevents an attacker who learned a peer's apiKey from extracting
|
|
148
148
|
* their service token by polling with a wrong secret.
|
|
149
149
|
*
|
|
150
|
-
* @param apiKey -
|
|
151
|
-
* @param apiSecret -
|
|
150
|
+
* @param apiKey - Application credential public key (optional if configureServiceAuth was called)
|
|
151
|
+
* @param apiSecret - Application credential secret (optional if configureServiceAuth was called)
|
|
152
152
|
*/
|
|
153
153
|
getServiceToken(apiKey?: string, apiSecret?: string): Promise<string>;
|
|
154
154
|
/**
|
|
@@ -305,6 +305,7 @@ export declare function OxyServicesFedCMMixin<T extends typeof OxyServicesBase>(
|
|
|
305
305
|
readonly DEFAULT_CONFIG_URL: "https://auth.oxy.so/fedcm.json";
|
|
306
306
|
readonly FEDCM_TIMEOUT: 15000;
|
|
307
307
|
readonly FEDCM_SILENT_TIMEOUT: 4000;
|
|
308
|
+
readonly FEDCM_ABORT_SETTLE_GRACE_MS: 500;
|
|
308
309
|
/**
|
|
309
310
|
* Check if FedCM is supported in the current browser
|
|
310
311
|
*/
|
|
@@ -27,7 +27,7 @@ export interface ServiceActingAsVerification {
|
|
|
27
27
|
/**
|
|
28
28
|
* Service app metadata attached to requests authenticated with service tokens.
|
|
29
29
|
* `scopes` reflects the scopes granted to the app at signup time (from the
|
|
30
|
-
* `
|
|
30
|
+
* `Application.scopes` field); route-level checks can require additional
|
|
31
31
|
* scope-narrowing via `requireScope()`.
|
|
32
32
|
*/
|
|
33
33
|
export interface ServiceApp {
|
|
@@ -16,7 +16,7 @@ import { OxyServicesLanguageMixin } from './OxyServices.language';
|
|
|
16
16
|
import { OxyServicesPaymentMixin } from './OxyServices.payment';
|
|
17
17
|
import { OxyServicesKarmaMixin } from './OxyServices.karma';
|
|
18
18
|
import { OxyServicesAssetsMixin } from './OxyServices.assets';
|
|
19
|
-
import {
|
|
19
|
+
import { OxyServicesApplicationsMixin } from './OxyServices.applications';
|
|
20
20
|
import { OxyServicesLocationMixin } from './OxyServices.location';
|
|
21
21
|
import { OxyServicesAnalyticsMixin } from './OxyServices.analytics';
|
|
22
22
|
import { OxyServicesDevicesMixin } from './OxyServices.devices';
|
|
@@ -36,7 +36,7 @@ import { OxyServicesAppDataMixin } from './OxyServices.appData';
|
|
|
36
36
|
* If you add a new mixin to `MIXIN_PIPELINE`, add it here too so its methods
|
|
37
37
|
* are visible without a cast.
|
|
38
38
|
*/
|
|
39
|
-
type AllMixinInstances = InstanceType<ReturnType<typeof OxyServicesAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesFedCMMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPopupAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesRedirectAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesSsoMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUserMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPrivacyMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesLanguageMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPaymentMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesKarmaMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAssetsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof
|
|
39
|
+
type AllMixinInstances = InstanceType<ReturnType<typeof OxyServicesAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesFedCMMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPopupAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesRedirectAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesSsoMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUserMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPrivacyMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesLanguageMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPaymentMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesKarmaMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAssetsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesApplicationsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesLocationMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAnalyticsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesDevicesMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesSecurityMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesFeaturesMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesTopicsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesManagedAccountsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesContactsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAppDataMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUtilityMixin<typeof OxyServicesBase>>>;
|
|
40
40
|
/**
|
|
41
41
|
* Constructor type for the fully composed mixin pipeline. Each mixin returns
|
|
42
42
|
* a new constructor that augments its input; reducing across the pipeline
|
|
@@ -83,6 +83,32 @@ export interface RunColdBootOptions<S> {
|
|
|
83
83
|
* the runner does not guard against an observer that itself throws.
|
|
84
84
|
*/
|
|
85
85
|
readonly onStepError?: (id: string, error: unknown) => void;
|
|
86
|
+
/**
|
|
87
|
+
* Optional HARD overall deadline (ms) for the entire ordered step loop —
|
|
88
|
+
* defense-in-depth so a single non-settling step can NEVER hang the whole
|
|
89
|
+
* cold boot forever.
|
|
90
|
+
*
|
|
91
|
+
* Each step's `run()` is raced against the SHARED remaining time. If a step
|
|
92
|
+
* fails to settle before the deadline, the runner abandons the await for that
|
|
93
|
+
* step (reporting it via `onStepDeadline`) and CONTINUES to the next step,
|
|
94
|
+
* each now racing against an already-expired deadline. This is deliberate:
|
|
95
|
+
* the runner keeps iterating so the TERMINAL step (e.g. the `/sso` bounce,
|
|
96
|
+
* whose `run()` performs its side effect synchronously before its first
|
|
97
|
+
* `await`) still gets to fire. A step that has nothing to contribute after
|
|
98
|
+
* the deadline simply doesn't settle and is skipped in turn.
|
|
99
|
+
*
|
|
100
|
+
* Per-step timeouts inside `run()` remain the first line of defense and
|
|
101
|
+
* should keep every step well under this budget on a healthy load; this only
|
|
102
|
+
* trips when one of them regresses (the production FedCM-silent hang). When
|
|
103
|
+
* omitted there is NO overall deadline (unchanged legacy behaviour).
|
|
104
|
+
*/
|
|
105
|
+
readonly overallDeadlineMs?: number;
|
|
106
|
+
/**
|
|
107
|
+
* Optional observer invoked once per step that was abandoned because the
|
|
108
|
+
* overall deadline expired before it settled. Receives the step `id`. Must
|
|
109
|
+
* not throw.
|
|
110
|
+
*/
|
|
111
|
+
readonly onStepDeadline?: (id: string) => void;
|
|
86
112
|
}
|
|
87
113
|
/**
|
|
88
114
|
* Run the ordered cold-boot steps and resolve to the first recovered session,
|
package/package.json
CHANGED
package/src/OxyServices.ts
CHANGED
|
@@ -85,7 +85,7 @@ import { composeOxyServices } from './mixins';
|
|
|
85
85
|
* - **Payment**: Payment processing
|
|
86
86
|
* - **Karma**: Karma system
|
|
87
87
|
* - **Assets**: File upload and asset management
|
|
88
|
-
* - **
|
|
88
|
+
* - **Applications**: Application, membership, and credential management
|
|
89
89
|
* - **Location**: Location-based features
|
|
90
90
|
* - **Analytics**: Analytics tracking
|
|
91
91
|
* - **Devices**: Device management
|
package/src/index.ts
CHANGED
|
@@ -62,6 +62,35 @@ export type {
|
|
|
62
62
|
} from './mixins/OxyServices.contacts';
|
|
63
63
|
export { OxyAppDataIdentifierError } from './mixins/OxyServices.appData';
|
|
64
64
|
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Applications (multi-user apps: membership, roles, credentials)
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
export type {
|
|
69
|
+
Application,
|
|
70
|
+
ApplicationMember,
|
|
71
|
+
ApplicationCredential,
|
|
72
|
+
ApplicationRole,
|
|
73
|
+
ApplicationType,
|
|
74
|
+
ApplicationStatus,
|
|
75
|
+
ApplicationMemberStatus,
|
|
76
|
+
ApplicationCredentialType,
|
|
77
|
+
ApplicationCredentialStatus,
|
|
78
|
+
ApplicationEnvironment,
|
|
79
|
+
CreateApplicationInput,
|
|
80
|
+
UpdateApplicationInput,
|
|
81
|
+
InviteApplicationMemberInput,
|
|
82
|
+
UpdateApplicationMemberInput,
|
|
83
|
+
TransferApplicationOwnershipInput,
|
|
84
|
+
CreateApplicationCredentialInput,
|
|
85
|
+
ApplicationCredentialWithSecret,
|
|
86
|
+
ApplicationUsagePeriod,
|
|
87
|
+
ApplicationUsageSummary,
|
|
88
|
+
ApplicationUsageByDay,
|
|
89
|
+
ApplicationUsageByEndpoint,
|
|
90
|
+
ApplicationUsageStats,
|
|
91
|
+
ApplicationSuccessResult,
|
|
92
|
+
} from './mixins/OxyServices.applications';
|
|
93
|
+
|
|
65
94
|
// ---------------------------------------------------------------------------
|
|
66
95
|
// Auth helpers (token refresh, error normalisation, retry policies)
|
|
67
96
|
// ---------------------------------------------------------------------------
|