Spaces:
Running
Running
Deploy Aureon OS (deploy/selfhost stack: nginx edge + fusion API x2 + console + HNC organ + redis + postgres; paper mode) (part 18)
f568a4f verified Download frontend/src/hooks/useIdentity.ts from GaryLeckey/aureon-os: direct link, hf CLI and curl.
- Browser
- Download file 3.36 kB
-
https://huggingface.co/spaces/GaryLeckey/aureon-os/resolve/main/frontend/src/hooks/useIdentity.ts
- Command line
-
hf download hf://spaces/GaryLeckey/aureon-os/frontend/src/hooks/useIdentity.ts
-
curl -L -o useIdentity.ts https://huggingface.co/spaces/GaryLeckey/aureon-os/resolve/main/frontend/src/hooks/useIdentity.ts
3.36 kB
| /** | |
| * useIdentity — which plane is this session on? | |
| * | |
| * The backend enforces a hard boundary: an operator sees the whole instance, a signed-in end user | |
| * sees only their own account plane (their keys, their reasoning, their billing) plus the read-only | |
| * showcase views. See `docs/architecture/MULTI_TENANT_AUTH.md`. | |
| * | |
| * Without this hook the console renders the operator's navigation to everyone and a signed-in user | |
| * discovers the boundary by collecting 403s. `GET /api/me` is the one identity call a tenant may | |
| * make — it reports the caller's own identity and deliberately nothing about the instance. | |
| * | |
| * Degrades quietly: if the endpoint is unreachable (older backend, gateway down) the hook reports | |
| * `unknown` and callers should fall back to showing everything, exactly as before this existed. | |
| */ | |
| import { useEffect, useState } from "react"; | |
| import { ApiError, api } from "@/services/apiClient"; | |
| export type IdentityKind = "open" | "admin" | "tenant" | "unknown"; | |
| export interface Identity { | |
| kind: IdentityKind; | |
| isAdmin: boolean; | |
| /** A short hash of the account id — never the raw JWT subject. */ | |
| tenantLabel: string | null; | |
| plane: "instance" | "account" | "unknown"; | |
| tenancyEnabled: boolean; | |
| authRequired: boolean; | |
| /** Route patterns this caller may reach; null for an operator (everything). */ | |
| allowedRoutes: string[] | null; | |
| } | |
| interface MeResponse { | |
| kind?: string; | |
| is_admin?: boolean; | |
| tenant_label?: string | null; | |
| plane?: string; | |
| tenancy_enabled?: boolean; | |
| auth_required?: boolean; | |
| allowed_routes?: string[] | null; | |
| } | |
| const UNKNOWN: Identity = { | |
| kind: "unknown", | |
| // Permissive when we genuinely do not know: the backend is the enforcer, so a wrong guess here | |
| // hides features from an operator rather than exposing anything to a tenant. | |
| isAdmin: true, | |
| tenantLabel: null, | |
| plane: "unknown", | |
| tenancyEnabled: false, | |
| authRequired: false, | |
| allowedRoutes: null, | |
| }; | |
| export function useIdentity(): { identity: Identity; loading: boolean; offline: boolean } { | |
| const [identity, setIdentity] = useState<Identity>(UNKNOWN); | |
| const [loading, setLoading] = useState(true); | |
| const [offline, setOffline] = useState(false); | |
| useEffect(() => { | |
| let cancelled = false; | |
| (async () => { | |
| try { | |
| const me = await api.get<MeResponse>("/api/me"); | |
| if (cancelled) return; | |
| const kind = (["open", "admin", "tenant"].includes(String(me.kind)) | |
| ? (me.kind as IdentityKind) | |
| : "unknown"); | |
| setIdentity({ | |
| kind, | |
| isAdmin: me.is_admin !== false, | |
| tenantLabel: me.tenant_label ?? null, | |
| plane: me.plane === "account" ? "account" : me.plane === "instance" ? "instance" : "unknown", | |
| tenancyEnabled: Boolean(me.tenancy_enabled), | |
| authRequired: Boolean(me.auth_required), | |
| allowedRoutes: Array.isArray(me.allowed_routes) ? me.allowed_routes : null, | |
| }); | |
| } catch (err) { | |
| if (cancelled) return; | |
| setOffline(err instanceof ApiError ? err.offline : true); | |
| setIdentity(UNKNOWN); | |
| } finally { | |
| if (!cancelled) setLoading(false); | |
| } | |
| })(); | |
| return () => { | |
| cancelled = true; | |
| }; | |
| }, []); | |
| return { identity, loading, offline }; | |
| } | |