@robosystems/core 0.7.0 → 0.7.2

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.
@@ -131,17 +131,22 @@ export function AuthProvider({ children, apiUrl = process.env.NEXT_PUBLIC_ROBOSY
131
131
  Promise.allSettled([clearGraphSelection(), clearEntitySelection()]),
132
132
  new Promise((resolve) => setTimeout(resolve, 2000)),
133
133
  ]);
134
- // Clear auth client cache and local user/session state
134
+ // Clear auth client cache and local storage state. Deliberately NO
135
+ // setUser(null) here: the hard navigation below tears the tree down
136
+ // anyway, and nulling the user first wakes AuthGuard, whose
137
+ // client-side redirect (→ /login → LoginRedirector → login home)
138
+ // can outrace the queued /logout navigation — the anchor session
139
+ // then survives and silently signs the user back in, undoing the
140
+ // logout (observed E2E under centralized login).
135
141
  authClient.clearAuthCache();
136
- setUser(null);
137
142
  setSessionWarning({ show: false, timeLeft: 0 });
138
143
  // Perform comprehensive cleanup of all user-specific data
139
144
  performLogoutCleanup();
140
145
  debugLog('Logout cleanup completed');
141
146
  // Always hard-redirect out of the authenticated area. A full-page
142
147
  // navigation (not a client-side router.push) guarantees the
143
- // authenticated tree tears down instead of AuthGuard flashing a blank
144
- // screen once user state clears. A forced logout (reason set, e.g.
148
+ // authenticated tree tears down without AuthGuard racing it (see
149
+ // above). A forced logout (reason set, e.g.
145
150
  // session_expired) goes to the login page so it can explain why the
146
151
  // session ended and let the user sign back in. A manual logout on a
147
152
  // product app chains through the login home's /logout so the anchor
@@ -1,4 +1,4 @@
1
- import type { APIKey, AuthResponse, AuthUser, CreateAPIKeyRequest, SSOTokenResponse } from './types';
1
+ import type { APIKey, AuthProviders, AuthResponse, AuthUser, CreateAPIKeyRequest, SSOTokenResponse } from './types';
2
2
  export declare class TokenExpiredError extends Error {
3
3
  constructor(message?: string);
4
4
  }
@@ -55,6 +55,14 @@ export declare class RoboSystemsAuthClient {
55
55
  }>;
56
56
  ssoComplete(sessionId: string): Promise<AuthResponse>;
57
57
  checkAuthentication(): Promise<AuthUser | null>;
58
+ /**
59
+ * Fetch the deployment's auth posture (which sign-in methods to render).
60
+ *
61
+ * A rendering hint, not a security boundary — the backend enforces every
62
+ * flag regardless of what the page shows. Any failure returns null and
63
+ * the caller renders the default password posture.
64
+ */
65
+ getAuthProviders(): Promise<AuthProviders | null>;
58
66
  clearAuthCache(): void;
59
67
  /**
60
68
  * Send password reset email
@@ -1,5 +1,5 @@
1
1
  var _a;
2
- import { checkPasswordStrength, client, completeSsoAuth, createUserApiKey, forgotPassword, generateSsoToken, getCurrentAuthUser, getInvitationPreview, getPasswordPolicy, listUserApiKeys, loginUser, logoutUser, refreshAuthSession, registerUser, resendVerificationEmail, resetPassword, revokeUserApiKey, ssoTokenExchange, validateResetToken, verifyEmail, } from '@robosystems/client';
2
+ import { checkPasswordStrength, client, completeSsoAuth, createUserApiKey, forgotPassword, generateSsoToken, getAuthProviders, getCurrentAuthUser, getInvitationPreview, getPasswordPolicy, listUserApiKeys, loginUser, logoutUser, refreshAuthSession, registerUser, resendVerificationEmail, resetPassword, revokeUserApiKey, ssoTokenExchange, validateResetToken, verifyEmail, } from '@robosystems/client';
3
3
  import * as sdkClientsModule from '@robosystems/client/clients';
4
4
  import { getToken, getValidToken } from './token-storage';
5
5
  // Global config hook for the clients package's lazy default singleton
@@ -491,6 +491,26 @@ export class RoboSystemsAuthClient {
491
491
  return null;
492
492
  }
493
493
  }
494
+ /**
495
+ * Fetch the deployment's auth posture (which sign-in methods to render).
496
+ *
497
+ * A rendering hint, not a security boundary — the backend enforces every
498
+ * flag regardless of what the page shows. Any failure returns null and
499
+ * the caller renders the default password posture.
500
+ */
501
+ async getAuthProviders() {
502
+ try {
503
+ const response = await getAuthProviders({ client: this.client });
504
+ const data = response.data;
505
+ if (!data || typeof data.password_auth !== 'boolean') {
506
+ return null;
507
+ }
508
+ return data;
509
+ }
510
+ catch (_a) {
511
+ return null;
512
+ }
513
+ }
494
514
  // Clear request deduplication cache (useful after login/logout)
495
515
  clearAuthCache() {
496
516
  this.lastAuthCheck = null;
@@ -14,6 +14,23 @@ export interface AuthResponse {
14
14
  expires_in?: number;
15
15
  refresh_threshold?: number;
16
16
  }
17
+ /**
18
+ * Deployment auth posture from `GET /v1/auth/providers`.
19
+ *
20
+ * A rendering hint, not a security boundary — the backend enforces every
21
+ * flag regardless of what the login surface shows. One byte-identical
22
+ * frontend build renders password-primary (managed), OIDC-primary
23
+ * (tenant), or closed-registration postures from this payload.
24
+ */
25
+ export interface AuthProviders {
26
+ password_auth: boolean;
27
+ oidc: {
28
+ enabled: boolean;
29
+ provider_label?: string | null;
30
+ };
31
+ registration: boolean;
32
+ passkeys: boolean;
33
+ }
17
34
  export interface LoginRequest {
18
35
  email: string;
19
36
  password: string;
package/index.d.ts CHANGED
@@ -26,7 +26,7 @@ export type { TaskCreateResponse, TaskMonitorState, TaskPollingOptions, TaskStat
26
26
  export { useGraphCreation, useOperationMonitoring, useRepositorySubscription, type OperationMonitorState, type UseOperationMonitoringResult, } from './task-monitoring/operationHooks';
27
27
  import { client } from '@robosystems/client';
28
28
  export { client };
29
- export type { APIKey, AppName, AuthContextType, AuthUser } from './auth-core';
29
+ export type { APIKey, AppName, AuthContextType, AuthProviders, AuthUser, } from './auth-core';
30
30
  export { CURRENT_APP } from './auth-core/config';
31
31
  export { getLoginHomeUrl, isLoginHome, LOGIN_HOME_APP, } from './auth-core/config';
32
32
  export { buildLoginHomeUrl, buildReturnTo, isSafeRelativePath, parseReturnTo, } from './auth-core/login-home';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robosystems/core",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "Shared RoboSystems frontend core library (auth, contexts, task monitoring, UI components) for the RoboSystems Next.js apps",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -27,7 +27,7 @@
27
27
  "tailwind-merge": "^3"
28
28
  },
29
29
  "peerDependencies": {
30
- "@robosystems/client": ">=1.2 <2",
30
+ "@robosystems/client": ">=1.9 <2",
31
31
  "flowbite-react": "^0.12.5",
32
32
  "next": ">=15 <17",
33
33
  "react": ">=18 <20",