@object-ui/auth 17.6.0 → 18.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/CHANGELOG.md +598 -0
- package/README.md +124 -19
- package/dist/ActiveOrganizationStorage.d.ts +32 -1
- package/dist/ActiveOrganizationStorage.d.ts.map +1 -1
- package/dist/ActiveOrganizationStorage.js +72 -3
- package/dist/AuthContext.d.ts +10 -3
- package/dist/AuthContext.d.ts.map +1 -1
- package/dist/AuthProvider.d.ts.map +1 -1
- package/dist/AuthProvider.js +101 -18
- package/dist/LoginForm.d.ts +35 -4
- package/dist/LoginForm.d.ts.map +1 -1
- package/dist/LoginForm.js +16 -4
- package/dist/RegisterForm.d.ts +21 -2
- package/dist/RegisterForm.d.ts.map +1 -1
- package/dist/RegisterForm.js +3 -4
- package/dist/SocialSignInButtons.d.ts +15 -2
- package/dist/SocialSignInButtons.d.ts.map +1 -1
- package/dist/SocialSignInButtons.js +3 -3
- package/dist/UserMenu.d.ts +1 -1
- package/dist/UserMenu.js +1 -1
- package/dist/auth-gate-events.d.ts +6 -4
- package/dist/auth-gate-events.d.ts.map +1 -1
- package/dist/auth-gate-events.js +11 -1
- package/dist/authStyles.d.ts +8 -3
- package/dist/authStyles.d.ts.map +1 -1
- package/dist/authStyles.js +8 -3
- package/dist/createAuthClient.d.ts +15 -1
- package/dist/createAuthClient.d.ts.map +1 -1
- package/dist/createAuthClient.js +54 -1
- package/dist/createAuthenticatedFetch.d.ts +5 -4
- package/dist/createAuthenticatedFetch.d.ts.map +1 -1
- package/dist/createAuthenticatedFetch.js +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/types.d.ts +53 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/useWorkspaceAdminStatus.d.ts +76 -27
- package/dist/useWorkspaceAdminStatus.d.ts.map +1 -1
- package/dist/useWorkspaceAdminStatus.js +146 -40
- package/package.json +6 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-gate-events.d.ts","sourceRoot":"","sources":["../src/auth-gate-events.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH
|
|
1
|
+
{"version":3,"file":"auth-gate-events.d.ts","sourceRoot":"","sources":["../src/auth-gate-events.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;GAWG;AAEH,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,IAAI,EAAE,cAAc,GAAG,kBAAkB,GAAG,yBAAyB,GAAG,MAAM,CAAC;IAC/E,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD,KAAK,QAAQ,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;AAG7C,eAAO,MAAM,cAAc;IACzB,qEAAqE;eAC1D,YAAY,GAAG,IAAI;IAK9B,4CAA4C;wBACxB,QAAQ,GAAG,MAAM,IAAI;CAI1C,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAUjF"}
|
package/dist/auth-gate-events.js
CHANGED
|
@@ -5,6 +5,16 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* The auth-policy codes the backend raises as a remediation gate. Hand-written:
|
|
10
|
+
* the spec vocabulary (`AuthGateCodeSchema`) is not in the `@objectstack/spec`
|
|
11
|
+
* this package builds against yet; derive from it once it is.
|
|
12
|
+
*/
|
|
13
|
+
const AUTH_GATE_CODES = new Set([
|
|
14
|
+
'MFA_REQUIRED',
|
|
15
|
+
'PASSWORD_EXPIRED',
|
|
16
|
+
'PASSWORD_RESET_REQUIRED',
|
|
17
|
+
]);
|
|
8
18
|
const listeners = new Set();
|
|
9
19
|
export const authGateEvents = {
|
|
10
20
|
/** Broadcast a gate to all subscribers (the active AuthProvider). */
|
|
@@ -33,7 +43,7 @@ export function detectAuthGate(status, body) {
|
|
|
33
43
|
if (!err || typeof err !== 'object')
|
|
34
44
|
return null;
|
|
35
45
|
const code = err.code;
|
|
36
|
-
if (code === '
|
|
46
|
+
if (typeof code === 'string' && AUTH_GATE_CODES.has(code)) {
|
|
37
47
|
const message = err.message;
|
|
38
48
|
return { code, message: typeof message === 'string' ? message : '' };
|
|
39
49
|
}
|
package/dist/authStyles.d.ts
CHANGED
|
@@ -13,10 +13,15 @@ import React from 'react';
|
|
|
13
13
|
*
|
|
14
14
|
* Consumers can override styling per-form by passing their own children
|
|
15
15
|
* inside an AuthShell, but the defaults aim to look premium out of the box.
|
|
16
|
+
*
|
|
17
|
+
* Sizes follow the console login artboard (objectui#12600): 40 px (`h-10`)
|
|
18
|
+
* fields and primary button, 13 px / 500 labels, one flat `--primary` fill on
|
|
19
|
+
* the button. Radii are the theme's own `rounded-lg`, so a host theme that
|
|
20
|
+
* re-scales `--radius` re-scales these with it.
|
|
16
21
|
*/
|
|
17
|
-
export declare const AUTH_INPUT_CLASS = "flex h-
|
|
18
|
-
export declare const AUTH_PRIMARY_BUTTON_CLASS = "inline-flex h-
|
|
19
|
-
export declare const AUTH_FIELD_LABEL_CLASS = "text-
|
|
22
|
+
export declare const AUTH_INPUT_CLASS = "flex h-10 w-full rounded-lg border border-input bg-background px-3.5 py-2 text-sm shadow-sm ring-offset-background transition-colors placeholder:text-muted-foreground hover:border-primary/40 focus-visible:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50";
|
|
23
|
+
export declare const AUTH_PRIMARY_BUTTON_CLASS = "inline-flex h-10 w-full items-center justify-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm ring-offset-background transition-[box-shadow,background-color,transform] hover:bg-primary/90 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 active:scale-[0.99] disabled:pointer-events-none disabled:opacity-60 motion-reduce:transition-none motion-reduce:active:transform-none";
|
|
24
|
+
export declare const AUTH_FIELD_LABEL_CLASS = "text-[13px] font-medium leading-none text-foreground";
|
|
20
25
|
export declare const AUTH_LINK_CLASS = "font-medium text-primary underline-offset-4 hover:underline focus-visible:outline-none focus-visible:underline";
|
|
21
26
|
/** Decorative spinner shown while a submit is pending. */
|
|
22
27
|
export declare function AuthSpinner(): React.JSX.Element;
|
package/dist/authStyles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authStyles.d.ts","sourceRoot":"","sources":["../src/authStyles.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B
|
|
1
|
+
{"version":3,"file":"authStyles.d.ts","sourceRoot":"","sources":["../src/authStyles.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,0XAC4V,CAAC;AAE1X,eAAO,MAAM,yBAAyB,mfAC4c,CAAC;AAEnf,eAAO,MAAM,sBAAsB,yDAAyD,CAAC;AAE7F,eAAO,MAAM,eAAe,mHACsF,CAAC;AAEnH,0DAA0D;AAC1D,wBAAgB,WAAW,sBAyB1B;AAED,8CAA8C;AAC9C,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,qBAiBlE;AAED,yDAAyD;AACzD,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,qBAgBlE;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,qBAgBjE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,KAAK,EACL,WAAW,GACZ,EAAE;IACD,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC/B,qBAgBA;AAED,kDAAkD;AAClD,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,qBAU/D;AAED,iEAAiE;AACjE,wBAAgB,WAAW,CAAC,EAAE,KAAY,EAAE,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,qBAW/D"}
|
package/dist/authStyles.js
CHANGED
|
@@ -6,10 +6,15 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
*
|
|
7
7
|
* Consumers can override styling per-form by passing their own children
|
|
8
8
|
* inside an AuthShell, but the defaults aim to look premium out of the box.
|
|
9
|
+
*
|
|
10
|
+
* Sizes follow the console login artboard (objectui#12600): 40 px (`h-10`)
|
|
11
|
+
* fields and primary button, 13 px / 500 labels, one flat `--primary` fill on
|
|
12
|
+
* the button. Radii are the theme's own `rounded-lg`, so a host theme that
|
|
13
|
+
* re-scales `--radius` re-scales these with it.
|
|
9
14
|
*/
|
|
10
|
-
export const AUTH_INPUT_CLASS = 'flex h-
|
|
11
|
-
export const AUTH_PRIMARY_BUTTON_CLASS = 'inline-flex h-
|
|
12
|
-
export const AUTH_FIELD_LABEL_CLASS = 'text-
|
|
15
|
+
export const AUTH_INPUT_CLASS = 'flex h-10 w-full rounded-lg border border-input bg-background px-3.5 py-2 text-sm shadow-sm ring-offset-background transition-colors placeholder:text-muted-foreground hover:border-primary/40 focus-visible:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50';
|
|
16
|
+
export const AUTH_PRIMARY_BUTTON_CLASS = 'inline-flex h-10 w-full items-center justify-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm ring-offset-background transition-[box-shadow,background-color,transform] hover:bg-primary/90 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 active:scale-[0.99] disabled:pointer-events-none disabled:opacity-60 motion-reduce:transition-none motion-reduce:active:transform-none';
|
|
17
|
+
export const AUTH_FIELD_LABEL_CLASS = 'text-[13px] font-medium leading-none text-foreground';
|
|
13
18
|
export const AUTH_LINK_CLASS = 'font-medium text-primary underline-offset-4 hover:underline focus-visible:outline-none focus-visible:underline';
|
|
14
19
|
/** Decorative spinner shown while a submit is pending. */
|
|
15
20
|
export function AuthSpinner() {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
|
-
import type { AuthClient, AuthClientConfig } from './types.js';
|
|
8
|
+
import type { AuthClient, AuthClientConfig, AuthUser, AuthClientSession } from './types.js';
|
|
9
9
|
/**
|
|
10
10
|
* Simple token storage backed by localStorage.
|
|
11
11
|
* Falls back to in-memory storage when localStorage is unavailable (SSR, tests).
|
|
@@ -38,6 +38,20 @@ export declare const TokenStorage: {
|
|
|
38
38
|
*/
|
|
39
39
|
subscribeRotation(listener: () => void): () => void;
|
|
40
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Take the preflight's `get-session` answer, once per page load (objectui#12808).
|
|
43
|
+
*
|
|
44
|
+
* Returns it only when it answers what the caller would ask: the same auth URL,
|
|
45
|
+
* and the Bearer still stored is the one the preflight validated (the server
|
|
46
|
+
* prefers the Bearer, so the cookie the preflight omitted cannot change the
|
|
47
|
+
* answer). Parsed exactly as `getSession()` parses the wire body, with the same
|
|
48
|
+
* token sync. Anything else, or a second call, returns `null` and the caller asks
|
|
49
|
+
* the server as before.
|
|
50
|
+
*/
|
|
51
|
+
export declare function takePreflightSession(authUrl: string): {
|
|
52
|
+
user: AuthUser;
|
|
53
|
+
session: AuthClientSession;
|
|
54
|
+
} | null;
|
|
41
55
|
/**
|
|
42
56
|
* Create an auth client instance backed by the official better-auth client.
|
|
43
57
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createAuthClient.d.ts","sourceRoot":"","sources":["../src/createAuthClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,UAAU,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"createAuthClient.d.ts","sourceRoot":"","sources":["../src/createAuthClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,UAAU,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAE1D,MAAM,YAAY,CAAC;AAKpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,YAAY;kBACD,MAAM,GAAG,IAAI;kCACD,IAAI;WAE/B,MAAM,GAAG,IAAI;eAST,MAAM,GAAG,IAAI;aAkBf,IAAI;IASb;;;OAGG;gCACyB,MAAM,IAAI,GAAG,MAAM,IAAI;CAMpD,CAAC;AAgKF;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,GACd;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,GAAG,IAAI,CAgBvD;AA8BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAksBrE"}
|
package/dist/createAuthClient.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
|
-
import { createAuthClient as createBetterAuthClient } from 'better-auth/client';
|
|
8
|
+
import { createAuthClient as createBetterAuthClient, parseJSON } from 'better-auth/client';
|
|
9
9
|
import { organizationClient, twoFactorClient } from 'better-auth/client/plugins';
|
|
10
10
|
import { AUTH_INVITATION_STATUSES, isAuthInvitationStatus } from './invitation-status.js';
|
|
11
11
|
const TOKEN_STORAGE_KEY = 'auth-session-token';
|
|
@@ -202,6 +202,46 @@ function resolveResetPasswordRedirect() {
|
|
|
202
202
|
}
|
|
203
203
|
return '/reset-password';
|
|
204
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* The slot the console's pre-React auth preflight (`apps/console/src/lib/
|
|
207
|
+
* auth-preflight.ts`) leaves its `get-session` answer in when the stored Bearer
|
|
208
|
+
* was valid: the auth URL it asked, the token it sent and the body as JSON text. The
|
|
209
|
+
* preflight runs before any bundle chunk that could import this package, so the
|
|
210
|
+
* slot is spelled by hand on both sides; the console's
|
|
211
|
+
* `sessionBootDedup.test.tsx` runs the preflight against this reader.
|
|
212
|
+
*/
|
|
213
|
+
const PREFLIGHT_SESSION_KEY = Symbol.for('objectui.authPreflightSession');
|
|
214
|
+
/**
|
|
215
|
+
* Take the preflight's `get-session` answer, once per page load (objectui#12808).
|
|
216
|
+
*
|
|
217
|
+
* Returns it only when it answers what the caller would ask: the same auth URL,
|
|
218
|
+
* and the Bearer still stored is the one the preflight validated (the server
|
|
219
|
+
* prefers the Bearer, so the cookie the preflight omitted cannot change the
|
|
220
|
+
* answer). Parsed exactly as `getSession()` parses the wire body, with the same
|
|
221
|
+
* token sync. Anything else, or a second call, returns `null` and the caller asks
|
|
222
|
+
* the server as before.
|
|
223
|
+
*/
|
|
224
|
+
export function takePreflightSession(authUrl) {
|
|
225
|
+
const holder = globalThis;
|
|
226
|
+
const slot = holder[PREFLIGHT_SESSION_KEY];
|
|
227
|
+
if (!slot || slot.taken)
|
|
228
|
+
return null;
|
|
229
|
+
slot.taken = true;
|
|
230
|
+
if (slot.authUrl !== authUrl || slot.token !== TokenStorage.get())
|
|
231
|
+
return null;
|
|
232
|
+
let payload;
|
|
233
|
+
try {
|
|
234
|
+
payload = parseJSON(slot.body, { strict: false });
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
if (!payload?.user || !payload.session)
|
|
240
|
+
return null;
|
|
241
|
+
if (payload.session.token)
|
|
242
|
+
TokenStorage.set(payload.session.token);
|
|
243
|
+
return { user: payload.user, session: payload.session };
|
|
244
|
+
}
|
|
205
245
|
/**
|
|
206
246
|
* Create a fetch wrapper that injects Bearer token from localStorage
|
|
207
247
|
* and captures updated tokens from the `set-auth-token` response header
|
|
@@ -360,6 +400,12 @@ export function createAuthClient(config) {
|
|
|
360
400
|
email: signUpData.email,
|
|
361
401
|
password: signUpData.password,
|
|
362
402
|
name: signUpData.name,
|
|
403
|
+
// objectui#10893 — the verification mail's link lands here. Without
|
|
404
|
+
// it better-auth writes `callbackURL=/`, and an invitee who registers
|
|
405
|
+
// from an invitation link is dropped on the workspace picker instead
|
|
406
|
+
// of the invitation. Only sent when the caller has somewhere to go,
|
|
407
|
+
// so the server default is untouched otherwise.
|
|
408
|
+
...(signUpData.callbackURL ? { callbackURL: signUpData.callbackURL } : {}),
|
|
363
409
|
});
|
|
364
410
|
if (error) {
|
|
365
411
|
throw toAuthError(error);
|
|
@@ -721,10 +767,17 @@ export function createAuthClient(config) {
|
|
|
721
767
|
return (data ?? []);
|
|
722
768
|
},
|
|
723
769
|
async createOrganization(orgData) {
|
|
770
|
+
// objectui#11908: the creator's zone rides the QUERY (`?timezone=`), the
|
|
771
|
+
// shape the server's create route reads it from; the body stays
|
|
772
|
+
// `{ name, slug, logo }`. better-auth's client proxy lifts
|
|
773
|
+
// `fetchOptions.query` onto the URL and keeps it out of the body. An
|
|
774
|
+
// absent or empty zone sends no parameter at all.
|
|
775
|
+
const { timezone } = orgData;
|
|
724
776
|
const { data, error } = await betterAuth.organization.create({
|
|
725
777
|
name: orgData.name,
|
|
726
778
|
slug: orgData.slug,
|
|
727
779
|
logo: orgData.logo,
|
|
780
|
+
...(timezone ? { fetchOptions: { query: { timezone } } } : {}),
|
|
728
781
|
});
|
|
729
782
|
if (error)
|
|
730
783
|
throw toAuthError(error, 'Failed to create organization');
|
|
@@ -21,16 +21,17 @@ export interface AuthenticatedAdapterOptions {
|
|
|
21
21
|
* so `@object-ui/auth`'s barrel, this package's tests and every consumer
|
|
22
22
|
* import the same symbol from the same place they did before.
|
|
23
23
|
*/
|
|
24
|
-
export { ActiveOrganizationStorage, SessionUserScope, purgePreviousUserClientState } from './ActiveOrganizationStorage.js';
|
|
24
|
+
export { ActiveOrganizationStorage, SessionUserScope, purgePreviousUserClientState, getSessionOwnerChangeCount, subscribeSessionOwnerChange, } from './ActiveOrganizationStorage.js';
|
|
25
25
|
export interface CreateAuthenticatedFetchOptions {
|
|
26
26
|
/**
|
|
27
27
|
* When true, requests whose URL resolves to a different origin than the
|
|
28
28
|
* current page are passed through to the bare global fetch — no
|
|
29
29
|
* Authorization, X-Tenant-ID, or Accept-Language headers are attached.
|
|
30
30
|
*
|
|
31
|
-
* Use this for fetches whose target URL
|
|
32
|
-
*
|
|
33
|
-
* that must never see the
|
|
31
|
+
* Use this for fetches whose target URL may come from metadata (a
|
|
32
|
+
* `type: 'api'` action's target) or that a host hands to the renderers as
|
|
33
|
+
* `apiFetch`: those may point at third-party hosts that must never see the
|
|
34
|
+
* platform bearer token.
|
|
34
35
|
*/
|
|
35
36
|
sameOriginOnly?: boolean;
|
|
36
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createAuthenticatedFetch.d.ts","sourceRoot":"","sources":["../src/createAuthenticatedFetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"createAuthenticatedFetch.d.ts","sourceRoot":"","sources":["../src/createAuthenticatedFetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,4BAA4B,EAC5B,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,gCAAgC,CAAC;AAExC,MAAM,WAAW,+BAA+B;IAC9C;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAYD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,CAAC,EAAE,+BAA+B,GACxC,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CA+GrE"}
|
|
@@ -15,7 +15,7 @@ import { ActiveOrganizationStorage } from './ActiveOrganizationStorage.js';
|
|
|
15
15
|
* so `@object-ui/auth`'s barrel, this package's tests and every consumer
|
|
16
16
|
* import the same symbol from the same place they did before.
|
|
17
17
|
*/
|
|
18
|
-
export { ActiveOrganizationStorage, SessionUserScope, purgePreviousUserClientState } from './ActiveOrganizationStorage.js';
|
|
18
|
+
export { ActiveOrganizationStorage, SessionUserScope, purgePreviousUserClientState, getSessionOwnerChangeCount, subscribeSessionOwnerChange, } from './ActiveOrganizationStorage.js';
|
|
19
19
|
/** True when `url` resolves to a different origin than the current page. */
|
|
20
20
|
function isCrossOrigin(url) {
|
|
21
21
|
if (typeof window === 'undefined' || !window.location)
|
|
@@ -106,7 +106,7 @@ export function createAuthenticatedFetch(options) {
|
|
|
106
106
|
// switcher, so reading it here means a language switch carries the new
|
|
107
107
|
// `Accept-Language` on every subsequent request — closing the gap where
|
|
108
108
|
// server-resolved labels stayed in the old language until a page refresh
|
|
109
|
-
// (issue #1319). We only fold it in for our own API calls, and never
|
|
109
|
+
// (issue objectstack-ai/objectstack#1319). We only fold it in for our own API calls, and never
|
|
110
110
|
// clobber an `Accept-Language` the caller set explicitly.
|
|
111
111
|
if (isApiCall && !headers.has('Accept-Language') && typeof document !== 'undefined') {
|
|
112
112
|
const lang = document.documentElement.lang;
|
|
@@ -122,7 +122,7 @@ export function createAuthenticatedFetch(options) {
|
|
|
122
122
|
//
|
|
123
123
|
// The console injects the same localStorage bearer from two places: the
|
|
124
124
|
// AUTH lane (sign-in / get-session / the auth endpoints) and THIS one — the
|
|
125
|
-
// adapter,
|
|
125
|
+
// adapter, the renderers' `apiFetch`, and every metadata `type: 'api'`
|
|
126
126
|
// action (`useConsoleActionRuntime`'s `apiHandler`). better-auth's
|
|
127
127
|
// server-side bearer plugin hands a rotated session token back in
|
|
128
128
|
// `set-auth-token` on whichever lane the call arrived over. Only the auth
|
package/dist/index.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export { PreviewBanner, type PreviewBannerProps } from './PreviewBanner.js';
|
|
|
33
33
|
export { createAuthClient, TokenStorage } from './createAuthClient.js';
|
|
34
34
|
export { normalizePhoneIdentifier, looksLikePhoneIdentifier } from './phone-identifier.js';
|
|
35
35
|
export { createAuthenticatedFetch, ActiveOrganizationStorage, type AuthenticatedAdapterOptions } from './createAuthenticatedFetch.js';
|
|
36
|
+
export { getSessionOwnerChangeCount, subscribeSessionOwnerChange } from './ActiveOrganizationStorage.js';
|
|
36
37
|
export { getUserInitials } from './types.js';
|
|
37
38
|
export { ORG_ROLE_OWNER, ORG_ROLE_ADMIN, ORG_ROLE_DELEGATED_ADMIN, ORG_ROLE_MEMBER, ORG_ROLES, ORG_ROLE_LABELS, orgRoleGrade, invitableOrgRoles, assignableOrgRoles, type OrgRole, } from './org-roles.js';
|
|
38
39
|
export { AUTH_INVITATION_STATUSES, isAuthInvitationStatus, type AuthInvitationStatus, } from './invitation-status.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAOvC,OAAO,EAAE,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAClG,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAClG,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAC1H,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,KAAK,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAOvC,OAAO,EAAE,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAClG,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAClG,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAC1H,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,KAAK,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAMtI,OAAO,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AACzG,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAO7C,OAAO,EACL,cAAc,EACd,cAAc,EACd,wBAAwB,EACxB,eAAe,EACf,SAAS,EACT,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,OAAO,GACb,MAAM,gBAAgB,CAAC;AAMxB,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,yBAAyB,EACzB,aAAa,EACb,aAAa,EACb,WAAW,EACX,eAAe,EACf,cAAc,EACd,YAAY,EACZ,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,QAAQ,EACR,iBAAiB,EACjB,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,sBAAsB,EACtB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,yBAAyB,EACzB,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,12 @@ export { PreviewBanner } from './PreviewBanner.js';
|
|
|
39
39
|
export { createAuthClient, TokenStorage } from './createAuthClient.js';
|
|
40
40
|
export { normalizePhoneIdentifier, looksLikePhoneIdentifier } from './phone-identifier.js';
|
|
41
41
|
export { createAuthenticatedFetch, ActiveOrganizationStorage } from './createAuthenticatedFetch.js';
|
|
42
|
+
// objectui#10193 — "the browser changed hands in this page-load". The purge on a
|
|
43
|
+
// change of session user clears storage; state already derived from it in
|
|
44
|
+
// memory (the UI language, first of all) is re-derived by whoever owns it, and
|
|
45
|
+
// these two are how that owner finds out — including one that mounts after the
|
|
46
|
+
// purge fired.
|
|
47
|
+
export { getSessionOwnerChangeCount, subscribeSessionOwnerChange } from './ActiveOrganizationStorage.js';
|
|
42
48
|
export { getUserInitials } from './types.js';
|
|
43
49
|
// Organization membership-role vocabulary — a CLOSED, framework-owned list of
|
|
44
50
|
// four (framework ADR-0108), re-exported from `@objectstack/spec`'s
|
package/dist/types.d.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import type React from 'react';
|
|
9
9
|
import type { AuthUser as SpecAuthUser, DelegableScope, DelegableAdminScope } from '@objectstack/spec/contracts';
|
|
10
10
|
import type { TenancyPosture } from '@objectstack/spec/security';
|
|
11
|
+
import type { AudiencePosture } from '@objectstack/spec/system';
|
|
11
12
|
import type { AuthInvitationStatus } from './invitation-status.js';
|
|
12
13
|
/**
|
|
13
14
|
* Authentication types for @object-ui/auth
|
|
@@ -96,6 +97,17 @@ export interface AuthClientSession {
|
|
|
96
97
|
* session, which is why the banner costs a normal session nothing.
|
|
97
98
|
*/
|
|
98
99
|
impersonatedBy?: string;
|
|
100
|
+
/**
|
|
101
|
+
* objectui#12809 — set by better-auth's organization plugin on the
|
|
102
|
+
* `GET /auth/get-session` answer: the id of the organization this session is
|
|
103
|
+
* active in, or `null` when it holds none. `AuthProvider` names the active
|
|
104
|
+
* organization from it and the `organization/list` answer, and asks for the
|
|
105
|
+
* member row at the same time. Absent when the answer did not come from
|
|
106
|
+
* `get-session` (a sign-in response) or the server has no organization
|
|
107
|
+
* plugin; the provider then asks the server for the active organization, as
|
|
108
|
+
* before.
|
|
109
|
+
*/
|
|
110
|
+
activeOrganizationId?: string | null;
|
|
99
111
|
}
|
|
100
112
|
/** Authentication state */
|
|
101
113
|
export interface AuthState {
|
|
@@ -120,6 +132,19 @@ export interface SignUpData {
|
|
|
120
132
|
name: string;
|
|
121
133
|
email: string;
|
|
122
134
|
password: string;
|
|
135
|
+
/**
|
|
136
|
+
* Where the email-verification link lands once the address is verified —
|
|
137
|
+
* e.g. the invitation page the user registered from (objectui#10893).
|
|
138
|
+
* Sent verbatim as better-auth's `/sign-up/email` `callbackURL`; omitted,
|
|
139
|
+
* the server's default (`/`) applies.
|
|
140
|
+
*
|
|
141
|
+
* better-auth accepts only a root-relative path (`/_console/…`) or an
|
|
142
|
+
* absolute URL on a trusted origin. Anything else — including a
|
|
143
|
+
* document-relative `./…` — is refused with `INVALID_CALLBACK_URL` and the
|
|
144
|
+
* WHOLE sign-up fails, so resolve an SPA route against its mount before
|
|
145
|
+
* passing it here.
|
|
146
|
+
*/
|
|
147
|
+
callbackURL?: string;
|
|
123
148
|
}
|
|
124
149
|
/** Auth client configuration */
|
|
125
150
|
export interface AuthClientConfig {
|
|
@@ -222,7 +247,7 @@ export interface AuthPublicConfig {
|
|
|
222
247
|
* better-auth admin plugin mounted server-side (`auth.plugins.admin`;
|
|
223
248
|
* SCIM forces it on). Gates the admin user-management surfaces — the
|
|
224
249
|
* sys_user create/set-password actions and the identity import wizard
|
|
225
|
-
* entry (framework#2766 / #2782).
|
|
250
|
+
* entry (framework#2766 / objectstack-ai/objectstack#2782).
|
|
226
251
|
*/
|
|
227
252
|
admin?: boolean;
|
|
228
253
|
/**
|
|
@@ -245,6 +270,23 @@ export interface AuthPublicConfig {
|
|
|
245
270
|
* Absent (older server / config not yet fetched) ⇒ no group affordances.
|
|
246
271
|
*/
|
|
247
272
|
tenancyPosture?: TenancyPosture;
|
|
273
|
+
/**
|
|
274
|
+
* Which audience posture is in force — the deployment's declared answer
|
|
275
|
+
* to "who may self-register here" (`invite_only`, the undeclared default;
|
|
276
|
+
* `email_domain`; `open`). A value, not a flag: the spec lists it in
|
|
277
|
+
* `PUBLIC_AUTH_CONFIG_NON_FLAG_KEYS` beside `tenancyPosture`.
|
|
278
|
+
*
|
|
279
|
+
* It does NOT replace `emailPassword.disableSignUp`, and the server does
|
|
280
|
+
* not force that flag from it: under `invite_only` the sign-up route still
|
|
281
|
+
* admits a pending invitee (and a fresh deployment's first owner), so the
|
|
282
|
+
* two keys together read "sign-up is open to invitees only". A surface
|
|
283
|
+
* that offers a generic sign-up therefore reads both — the console's
|
|
284
|
+
* login and register pages and `@object-ui/app-shell`'s exported default
|
|
285
|
+
* ones do, through app-shell's `decideSignUpOffer` (objectui#11691,
|
|
286
|
+
* objectui#11705). Absent (older server / config not yet fetched) ⇒
|
|
287
|
+
* `disableSignUp` alone decides, as it did before the key existed.
|
|
288
|
+
*/
|
|
289
|
+
audiencePosture?: AudiencePosture;
|
|
248
290
|
};
|
|
249
291
|
}
|
|
250
292
|
/** Options when initiating a third-party sign-in */
|
|
@@ -330,11 +372,20 @@ export interface AuthClient {
|
|
|
330
372
|
signInWithProvider: (providerId: string, options?: SignInWithProviderOptions) => Promise<void>;
|
|
331
373
|
/** List organizations the current user belongs to */
|
|
332
374
|
listOrganizations: () => Promise<AuthOrganization[]>;
|
|
333
|
-
/**
|
|
375
|
+
/**
|
|
376
|
+
* Create a new organization.
|
|
377
|
+
*
|
|
378
|
+
* `timezone` (objectui#11908) is the creator's IANA zone, for example the
|
|
379
|
+
* browser's `Intl.DateTimeFormat().resolvedOptions().timeZone`. It travels
|
|
380
|
+
* as the `timezone` QUERY parameter of `POST /organization/create`, never in
|
|
381
|
+
* the body, which stays `{ name, slug, logo }`. Omitted or empty, nothing is
|
|
382
|
+
* sent and the server keeps its default zone; the server judges the value.
|
|
383
|
+
*/
|
|
334
384
|
createOrganization: (data: {
|
|
335
385
|
name: string;
|
|
336
386
|
slug: string;
|
|
337
387
|
logo?: string;
|
|
388
|
+
timezone?: string;
|
|
338
389
|
}) => Promise<AuthOrganization>;
|
|
339
390
|
/** Set the active organization for the current session */
|
|
340
391
|
setActiveOrganization: (orgId: string) => Promise<AuthOrganization | null>;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EACV,QAAQ,IAAI,YAAY,EACxB,cAAc,EACd,mBAAmB,EACpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;GAEG;AAEH;;;;;;;;;;;;GAYG;AACH,YAAY,EAAE,cAAc,EAAE,CAAC;AAE/B;;;;;;;;;;;GAWG;AACH,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,QAAS,SAAQ,YAAY;IAC5C,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IAUd,gCAAgC;IAChC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+BAA+B;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAWjG;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IAChC,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export interface WorkspaceAdminStatus {
|
|
15
15
|
/**
|
|
16
|
-
* True only when adminship is CONFIRMED by one of the
|
|
16
|
+
* True only when adminship is CONFIRMED by one of the legs below.
|
|
17
17
|
* While `isResolved` is false this is `false` because nothing has said
|
|
18
18
|
* otherwise yet — NOT because the viewer is known not to be an admin.
|
|
19
19
|
*/
|
|
@@ -30,29 +30,76 @@ export interface WorkspaceAdminStatus {
|
|
|
30
30
|
* has finished resolving.
|
|
31
31
|
*
|
|
32
32
|
* Sources considered (any one is sufficient):
|
|
33
|
-
* -
|
|
34
|
-
* -
|
|
35
|
-
* that still store an admin role on the user row.
|
|
36
|
-
* - `user.
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
33
|
+
* - LEG 1 — the active organization member row (multi-tenant mode).
|
|
34
|
+
* - LEG 2 — the top-level `user.role` scalar from the session: legacy
|
|
35
|
+
* deployments that still store an admin role on the user row.
|
|
36
|
+
* - LEG 3a — `user.isPlatformAdmin` from the session: the server's ADR-0095
|
|
37
|
+
* posture RUNG, and the ONLY leg that sees a platform administrator whose
|
|
38
|
+
* adminship comes from the `admin_full_access` permission set. On a
|
|
39
|
+
* single-tenant deployment there is no member row to read (leg 1) and the
|
|
40
|
+
* server deliberately no longer overwrites `user.role` (leg 2), so this
|
|
41
|
+
* flag is the whole signal for that viewer. Measured on a live protocol-17
|
|
42
|
+
* server in objectui#5389 — the captured payload there carries
|
|
43
|
+
* `isPlatformAdmin: true` — and pinned by
|
|
44
44
|
* `__tests__/workspaceAdminPositions-5389.test.tsx`.
|
|
45
|
+
* - LEG 3b — `user.positions[]` from the session, judged against
|
|
46
|
+
* {@link ADMIN_POSITION_NAMES} rather than {@link ADMIN_ROLES}: the
|
|
47
|
+
* canonical TENANT-scoped identity names the server derives from the active
|
|
48
|
+
* organization's membership row (ADR-0068 D1/D2, renamed from `roles` by
|
|
49
|
+
* ADR-0090 D3). This is what lets a tenant administrator resolve on the
|
|
50
|
+
* first frame instead of waiting for leg 1 (see the objectui#5619 section
|
|
51
|
+
* below).
|
|
45
52
|
*
|
|
46
|
-
*
|
|
47
|
-
* alongside the retired `roles` (ADR-0090 D3 renamed with no deprecation
|
|
48
|
-
* window and bans resurrecting the old name as a fallback), and not alongside
|
|
49
|
-
* the derived `user.isPlatformAdmin` either — that flag is computed by the
|
|
50
|
-
* server as `'platform_admin' in positions` from the same expression, so
|
|
51
|
-
* reading both would be two spellings for one fact with no way to disagree
|
|
52
|
-
* usefully and every way to drift.
|
|
53
|
+
* ## Why 3a and 3b are two legs and not one (objectui#8291)
|
|
53
54
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
55
|
+
* This docblock used to argue the opposite, and a future reader who finds that
|
|
56
|
+
* argument standing will re-introduce the defect it now describes. It said:
|
|
57
|
+
* do not read `user.isPlatformAdmin` alongside `positions`, because the server
|
|
58
|
+
* computes the flag as `'platform_admin' in positions` from the same
|
|
59
|
+
* expression, so reading both would be two spellings for one fact with no way
|
|
60
|
+
* to disagree usefully and every way to drift.
|
|
61
|
+
*
|
|
62
|
+
* **That was true and it is now false.** Framework objectstack#15948 (a
|
|
63
|
+
* declared BREAKING change) redefined what `positions[]` IS. It used to be the
|
|
64
|
+
* `sys_user.role` scalar split on commas; it is now built by
|
|
65
|
+
* `resolveUserAuthzGrants` and carries ADR-0057 D4 `sys_user_position`
|
|
66
|
+
* assignments. That table is `apiEnabled` and its `position` values are
|
|
67
|
+
* unconstrained, so a caller holding tenant-administration authority can mint
|
|
68
|
+
* a row spelling `platform_admin` for one of their own users — and the name
|
|
69
|
+
* lands on `positions[]` verbatim.
|
|
70
|
+
*
|
|
71
|
+
* The two therefore no longer say one thing:
|
|
72
|
+
*
|
|
73
|
+
* - `isPlatformAdmin` is `grants.posture === 'PLATFORM_ADMIN'` — derived from
|
|
74
|
+
* an UNSCOPED `admin_full_access` grant (or a verified email on the
|
|
75
|
+
* deployment's declared administrator list) and from nothing else. It is
|
|
76
|
+
* byte-for-byte what the server's own `hasPlatformAdminStanding` returns.
|
|
77
|
+
* - `positions[]` is the security AXIS, which is a wider thing: it is the set
|
|
78
|
+
* of names a request resolves to, including names a tenant wrote.
|
|
79
|
+
*
|
|
80
|
+
* They can now disagree, and when they do **the rung is right** — enforcement
|
|
81
|
+
* agrees with the rung, so the array's extra name buys nothing except a
|
|
82
|
+
* Console that paints platform-administrator surfaces at a principal every
|
|
83
|
+
* underlying call refuses. `resolve-authz-context.ts` states the rule at
|
|
84
|
+
* `hasPlatformAdminStanding`: read the RUNG, never
|
|
85
|
+
* `positions.includes('platform_admin')`. The framework moved four server-side
|
|
86
|
+
* sites onto it (`plugin-sharing`, `plugin-approvals`, `plugin-security`,
|
|
87
|
+
* `runtime`); this hook is the same read on the client side of the wire.
|
|
88
|
+
*
|
|
89
|
+
* ⛔ So: never put `platform_admin` back into {@link ADMIN_POSITION_NAMES},
|
|
90
|
+
* and never widen leg 3b back to {@link ADMIN_ROLES}. The name is not the
|
|
91
|
+
* authority. Every server that publishes `positions` publishes
|
|
92
|
+
* `isPlatformAdmin` beside it — `customSession` returns them in one object
|
|
93
|
+
* literal — so nothing is lost by reading the narrow one.
|
|
94
|
+
*
|
|
95
|
+
* `positions` also remains the ONE published spelling of the array itself. It
|
|
96
|
+
* is deliberately not read alongside the retired `roles` (ADR-0090 D3 renamed
|
|
97
|
+
* with no deprecation window and bans resurrecting the old name as a
|
|
98
|
+
* fallback).
|
|
99
|
+
*
|
|
100
|
+
* In preview-mode / no-auth-enabled mode the provider seeds an admin user
|
|
101
|
+
* (`role: 'admin'`, which leg 2 reads), so this returns `isAdmin: true` for
|
|
102
|
+
* dev/demo setups.
|
|
56
103
|
*
|
|
57
104
|
* ## Why this returns a pair and not a boolean (objectui#5619)
|
|
58
105
|
*
|
|
@@ -68,18 +115,20 @@ export interface WorkspaceAdminStatus {
|
|
|
68
115
|
* console chrome dropped and re-added a nav entry, and `AppContent` fired a
|
|
69
116
|
* `<Navigate to="/home" replace>` that the later flip cannot undo.
|
|
70
117
|
*
|
|
71
|
-
* Legs 2 and
|
|
118
|
+
* Legs 2 and 3b DO cover that viewer whenever the session was minted with an
|
|
72
119
|
* active organization stamped on it — framework `auth-manager.ts` reads
|
|
73
120
|
* `session.activeOrganizationId` and, when it is set, maps the member row into
|
|
74
|
-
* `positions[]` as `org_owner`/`org_admin`.
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
121
|
+
* `positions[]` as `org_owner`/`org_admin`. Those two names are exactly why
|
|
122
|
+
* objectui#8291 kept leg 3b alive rather than deleting the array read
|
|
123
|
+
* outright. The window is therefore not "every tenant admin" as first
|
|
124
|
+
* reported, but "every session that reaches the console without that stamp",
|
|
125
|
+
* which is exactly the path `refreshOrganizations`' ADR-0081 repair exists to
|
|
126
|
+
* serve.
|
|
78
127
|
*
|
|
79
128
|
* `isResolved` is deliberately true the moment `isAdmin` is true: a confirmed
|
|
80
129
|
* admin is a final answer, and the legs still in flight can only agree with it.
|
|
81
130
|
* Callers therefore never wait on a verdict they already have — an admin
|
|
82
|
-
* detected through `positions` pays nothing for this gate.
|
|
131
|
+
* detected through the rung or through `positions` pays nothing for this gate.
|
|
83
132
|
*/
|
|
84
133
|
export declare function useWorkspaceAdminStatus(): WorkspaceAdminStatus;
|
|
85
134
|
//# sourceMappingURL=useWorkspaceAdminStatus.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWorkspaceAdminStatus.d.ts","sourceRoot":"","sources":["../src/useWorkspaceAdminStatus.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"useWorkspaceAdminStatus.d.ts","sourceRoot":"","sources":["../src/useWorkspaceAdminStatus.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAsFH;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwGG;AACH,wBAAgB,uBAAuB,IAAI,oBAAoB,CAmB9D"}
|