@oxyhq/core 3.18.1 → 4.0.1

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 (52) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/OxyServices.js +3 -2
  3. package/dist/cjs/i18n/locales/en-US.json +391 -17
  4. package/dist/cjs/i18n/locales/es-ES.json +391 -17
  5. package/dist/cjs/i18n/locales/locales/en-US.json +391 -17
  6. package/dist/cjs/i18n/locales/locales/es-ES.json +391 -17
  7. package/dist/cjs/mixins/OxyServices.accounts.js +480 -0
  8. package/dist/cjs/mixins/OxyServices.connectedApps.js +73 -0
  9. package/dist/cjs/mixins/OxyServices.utility.js +3 -2
  10. package/dist/cjs/mixins/index.js +9 -6
  11. package/dist/esm/.tsbuildinfo +1 -1
  12. package/dist/esm/OxyServices.js +3 -2
  13. package/dist/esm/i18n/locales/en-US.json +391 -17
  14. package/dist/esm/i18n/locales/es-ES.json +391 -17
  15. package/dist/esm/i18n/locales/locales/en-US.json +391 -17
  16. package/dist/esm/i18n/locales/locales/es-ES.json +391 -17
  17. package/dist/esm/mixins/OxyServices.accounts.js +477 -0
  18. package/dist/esm/mixins/OxyServices.connectedApps.js +70 -0
  19. package/dist/esm/mixins/OxyServices.utility.js +3 -2
  20. package/dist/esm/mixins/index.js +9 -6
  21. package/dist/types/.tsbuildinfo +1 -1
  22. package/dist/types/OxyServices.d.ts +3 -2
  23. package/dist/types/index.d.ts +2 -3
  24. package/dist/types/mixins/OxyServices.accounts.d.ts +642 -0
  25. package/dist/types/mixins/OxyServices.auth.d.ts +1 -1
  26. package/dist/types/mixins/OxyServices.connectedApps.d.ts +168 -0
  27. package/dist/types/mixins/OxyServices.utility.d.ts +6 -3
  28. package/dist/types/mixins/index.d.ts +3 -4
  29. package/package.json +1 -1
  30. package/src/OxyServices.ts +3 -2
  31. package/src/i18n/locales/en-US.json +391 -17
  32. package/src/i18n/locales/es-ES.json +391 -17
  33. package/src/index.ts +33 -34
  34. package/src/mixins/OxyServices.accounts.ts +1079 -0
  35. package/src/mixins/OxyServices.auth.ts +1 -1
  36. package/src/mixins/OxyServices.connectedApps.ts +165 -0
  37. package/src/mixins/OxyServices.utility.ts +7 -4
  38. package/src/mixins/__tests__/accounts.test.ts +667 -0
  39. package/src/mixins/__tests__/connectedApps.test.ts +1 -1
  40. package/src/mixins/index.ts +11 -9
  41. package/dist/cjs/mixins/OxyServices.applications.js +0 -350
  42. package/dist/cjs/mixins/OxyServices.managedAccounts.js +0 -143
  43. package/dist/cjs/mixins/OxyServices.workspaces.js +0 -181
  44. package/dist/esm/mixins/OxyServices.applications.js +0 -347
  45. package/dist/esm/mixins/OxyServices.managedAccounts.js +0 -140
  46. package/dist/esm/mixins/OxyServices.workspaces.js +0 -178
  47. package/dist/types/mixins/OxyServices.applications.d.ts +0 -496
  48. package/dist/types/mixins/OxyServices.managedAccounts.d.ts +0 -145
  49. package/dist/types/mixins/OxyServices.workspaces.d.ts +0 -219
  50. package/src/mixins/OxyServices.applications.ts +0 -773
  51. package/src/mixins/OxyServices.managedAccounts.ts +0 -173
  52. package/src/mixins/OxyServices.workspaces.ts +0 -351
@@ -12,7 +12,7 @@ import type {
12
12
  import type { UserNameResponse } from '@oxyhq/contracts';
13
13
  import type { SessionLoginResponse } from '../models/session';
14
14
  import type { OxyServicesBase } from '../OxyServices.base';
15
- import type { PublicApplication } from './OxyServices.applications';
15
+ import type { PublicApplication } from './OxyServices.connectedApps';
16
16
  import { OxyAuthenticationError } from '../OxyServices.errors';
17
17
  import { KeyManager } from '../crypto/keyManager';
18
18
  import { SignatureService } from '../crypto/signatureService';
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Connected Apps (OAuth consent) Methods Mixin
3
+ *
4
+ * The user-facing OAuth-consent surface: resolving the PUBLIC identity of a
5
+ * requesting application (for consent/authorize/device-flow screens), and
6
+ * viewing/revoking the THIRD-PARTY applications the current user has authorized.
7
+ *
8
+ * This is deliberately separate from account ownership (`OxyServices.accounts.ts`):
9
+ * an account owns and manages its own applications, whereas this mixin is about a
10
+ * user granting/revoking another party's app access to their own data. None of
11
+ * these methods touch the account graph.
12
+ *
13
+ * Reference connected apps by their application `_id` (`applicationId`), NOT a
14
+ * credential/client id, so a grant — and its revocation — survive credential
15
+ * rotation.
16
+ */
17
+ import type { OxyServicesBase } from '../OxyServices.base';
18
+ // `PublicApplication.type` reuses the canonical Application classification, which
19
+ // is owned by the accounts mixin (home of the Application model). Type-only import.
20
+ import type { ApplicationType } from './OxyServices.accounts';
21
+ import { CACHE_TIMES } from './mixinHelpers';
22
+
23
+ /**
24
+ * Sanitized, PUBLIC application identity returned by the API when resolving a
25
+ * cross-app/OAuth client to a registered application.
26
+ *
27
+ * This shape carries NO sensitive or membership fields — it is safe to display
28
+ * unauthenticated in consent/authorize screens and device-flow approval UIs. The
29
+ * API resolves a `client_id` (OAuth credential public key) to the owning
30
+ * application and projects only the fields below. `id` is the application's
31
+ * `_id` as a string.
32
+ */
33
+ export interface PublicApplication {
34
+ /** The application's Mongo `_id` as a string. */
35
+ id: string;
36
+ /** Human-readable application name shown to the user. */
37
+ name: string;
38
+ /** Optional short description of what the application does. */
39
+ description?: string;
40
+ /** Optional icon URL for the application. */
41
+ icon?: string;
42
+ /** Optional public website/homepage URL for the application. */
43
+ websiteUrl?: string;
44
+ /** Application classification (set by Oxy platform staff). */
45
+ type: ApplicationType;
46
+ /** Whether the application is an officially endorsed Oxy application. */
47
+ isOfficial: boolean;
48
+ /** Whether the application is an internal Oxy ecosystem application. */
49
+ isInternal: boolean;
50
+ /** OAuth scopes the application is configured to request. */
51
+ scopes: string[];
52
+ /** Optional display name of the developer/owner organisation. */
53
+ developerName?: string;
54
+ }
55
+
56
+ /**
57
+ * A connected (OAuth-authorized) application from the current user's point of
58
+ * view: an application the user has granted access to via the consent flow.
59
+ *
60
+ * Returned by `GET /auth/grants` and rendered in the user-facing "Connected
61
+ * apps" management surface. Keyed by `applicationId` (the application's Mongo
62
+ * `_id`) rather than a credential/client id, so the grant — and a subsequent
63
+ * {@link OxyServicesConnectedAppsMixin.revokeAppGrant} — survive credential
64
+ * rotation. This is a display shape: it carries the application's name/logo and
65
+ * the granted scopes, never any membership or credential material.
66
+ */
67
+ export interface ConnectedApp {
68
+ /** The connected application's Mongo `_id`. Use this to revoke the grant. */
69
+ applicationId: string;
70
+ /** Human-readable application name shown to the user. */
71
+ name: string;
72
+ /** Optional logo URL for the application. */
73
+ logoUrl?: string;
74
+ /** OAuth scopes the user has granted to the application. */
75
+ scopes: string[];
76
+ /** ISO timestamp of when the user first authorized the application. */
77
+ firstGrantedAt: string;
78
+ /** ISO timestamp of when the grant was last exercised. */
79
+ lastUsedAt: string;
80
+ }
81
+
82
+ export function OxyServicesConnectedAppsMixin<T extends typeof OxyServicesBase>(Base: T) {
83
+ return class extends Base {
84
+ constructor(...args: any[]) {
85
+ super(...(args as [any]));
86
+ }
87
+
88
+ /**
89
+ * Resolve an OAuth client identifier to the owning application's PUBLIC
90
+ * identity. No authentication required — the API returns only sanitized,
91
+ * display-safe metadata ({@link PublicApplication}). Use this to render the
92
+ * requesting application's name/icon in consent, authorize, and device-flow
93
+ * approval UIs before any session exists.
94
+ *
95
+ * @param clientId - The OAuth `client_id` (an active credential's public
96
+ * key). URL-encoded before being placed in the path.
97
+ */
98
+ async getPublicApplication(clientId: string): Promise<PublicApplication> {
99
+ try {
100
+ const res = await this.makeRequest<{ application: PublicApplication }>(
101
+ 'GET',
102
+ `/auth/oauth/client/${encodeURIComponent(clientId)}`,
103
+ undefined,
104
+ { cache: true, cacheTTL: CACHE_TIMES.MEDIUM },
105
+ );
106
+ return res.application;
107
+ } catch (error) {
108
+ throw this.handleError(error);
109
+ }
110
+ }
111
+
112
+ /**
113
+ * List the OAuth-authorized applications the current user has connected —
114
+ * the third-party apps the user granted access to via the consent flow.
115
+ * Each entry is a {@link ConnectedApp} carrying the application's display
116
+ * identity, the granted scopes, and when the grant was first made and last
117
+ * exercised. Requires an authenticated session.
118
+ *
119
+ * Backed by `GET /auth/grants`. The response is briefly cached
120
+ * (identity-scoped); {@link revokeAppGrant} busts that cache so a revoke is
121
+ * reflected on the next read.
122
+ */
123
+ async listConnectedApps(): Promise<ConnectedApp[]> {
124
+ try {
125
+ return await this.makeRequest<ConnectedApp[]>(
126
+ 'GET',
127
+ '/auth/grants',
128
+ undefined,
129
+ { cache: true, cacheTTL: CACHE_TIMES.SHORT },
130
+ );
131
+ } catch (error) {
132
+ throw this.handleError(error);
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Revoke the current user's grant for a connected application, identified by
138
+ * its application `_id` (a {@link ConnectedApp.applicationId}, NOT a
139
+ * credential/client id — keyed by application so the revocation survives
140
+ * credential rotation). After this the application can no longer act on the
141
+ * user's behalf until it is re-authorized.
142
+ *
143
+ * Backed by `DELETE /auth/grants/:applicationId`. On success the cached
144
+ * connected-apps list (`GET:/auth/grants`) is invalidated so the next
145
+ * {@link listConnectedApps} read reflects the removal.
146
+ *
147
+ * @param applicationId - The connected application's Mongo `_id`.
148
+ */
149
+ async revokeAppGrant(applicationId: string): Promise<void> {
150
+ try {
151
+ await this.makeRequest<{ revoked: boolean }>(
152
+ 'DELETE',
153
+ `/auth/grants/${applicationId}`,
154
+ undefined,
155
+ { cache: false },
156
+ );
157
+ // A revoke removes an entry from the user's connected-apps list; bust
158
+ // the cached `GET /auth/grants` so the next read re-fetches.
159
+ this.clearCacheEntry('GET:/auth/grants');
160
+ } catch (error) {
161
+ throw this.handleError(error);
162
+ }
163
+ }
164
+ };
165
+ }
@@ -27,8 +27,10 @@ interface JwtPayload {
27
27
  }
28
28
 
29
29
  /**
30
- * Result from the managed-accounts verification endpoint.
31
- * Indicates whether a user is authorized to act as a given managed account.
30
+ * Result from the account acting-as verification endpoint
31
+ * (`GET /accounts/verify-acting-as`). Indicates whether a user is authorized to
32
+ * act as a given account. The `account:act_as` capability is granted only to the
33
+ * `owner`, `admin`, and `editor` account roles.
32
34
  */
33
35
  interface ActingAsVerification {
34
36
  authorized: boolean;
@@ -160,7 +162,8 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
160
162
  }
161
163
 
162
164
  /**
163
- * Verify that a user is authorized to act as a managed account.
165
+ * Verify that a user is authorized to act as an account (direct membership
166
+ * or inherited via an ancestor). Backed by `GET /accounts/verify-acting-as`.
164
167
  * Results are cached in-memory for 5 minutes to avoid repeated API calls.
165
168
  *
166
169
  * @internal Used by the auth() middleware — not part of the public API
@@ -179,7 +182,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
179
182
  try {
180
183
  const result = await this.makeRequest<ActingAsVerification>(
181
184
  'GET',
182
- '/managed-accounts/verify',
185
+ '/accounts/verify-acting-as',
183
186
  { accountId, userId },
184
187
  { cache: false, retry: false, timeout: 5000 }
185
188
  );