/** * @vantageos/cloud-identity 0.4.0 — Human-path resolver (Clerk → { tenant, * subject, role }). * * Additive-only: does not import any Clerk SDK, and does not modify any * existing export. The caller resolves a Clerk session (or any session * provider with an equivalent shape) *outside* this package and passes in a * plain, already-resolved object; this module only normalizes it into the * package's contract. * * `role` is a NEW literal union (`owner | admin | member | client`), * distinct from `workspaceRoleSchema` (`Admin | Editor | Viewer`) in * `./tenancy-domain.ts` — the two are unrelated vocabularies (workspace * membership role vs. organization-account role) and are never conflated. * * Consistent with the package's "a right is presented, never inferred from * an absence" contract: a session with no organization refuses (throws), * and an unrecognized/absent Clerk org role refuses (throws) rather than * silently defaulting to a role. */ import { z } from "zod"; export declare const humanAccountRoleSchema: z.ZodEnum<{ owner: "owner"; admin: "admin"; member: "member"; client: "client"; }>; export type HumanAccountRole = z.infer; /** * The minimal shape this package needs out of an already-resolved Clerk * session (e.g. the object returned by Clerk's own `auth()` in a Next.js * server context). No Clerk SDK type is imported — this is a structural * shape the caller supplies directly. */ export type ClerkSessionLike = { orgId?: string | null; userId?: string | null; orgRole?: string | null; }; export type ResolvedHumanIdentity = { tenant: string; subject: string; role: HumanAccountRole; }; /** * @security ⚠️ DECODE/NORMALIZE-ONLY. NOT AUTHENTICATION. NOT VERIFICATION. * * This function does NOT authenticate a request and does NOT verify * anything. It NORMALIZES a session that the caller has ALREADY verified * upstream — e.g. via Clerk's own server-side `auth()` in a Next.js/Convex * server context — into this package's `{ tenant, subject, role }` contract. * * Passing an unverified, client-supplied object here (for example * `req.body`, a query-string payload, or anything else an attacker * controls) makes THAT object the trusted source of `tenant`, `subject`, * AND `role` — a privilege-escalation bug. The shape checks below (missing * orgId/userId/orgRole) only guard against malformed input; they perform * NO signature check, NO issuer check, NO session-validity check. * * Callers MUST verify the session upstream (Clerk `auth()` server-side, or * an equivalent signed-session verifier) BEFORE calling this function. Only * pass in the object Clerk itself already verified — never pass through an * unverified request body. * * Resolves an already-verified, framework-agnostic Clerk session object into * the package's `{ tenant, subject, role }` contract. * * - throws when `session` is null/undefined ("Unauthenticated: no * session.") — same refusal message class as `requireTenantId`'s * session branch, for consistent error handling across both resolvers. * - throws when `session.orgId` is missing or empty ("No active * organization on this session...") — human path is cloud fail-closed, * same invariant as `requireTenantId`. * - throws when `session.userId` is missing or empty. * - throws when `session.orgRole` is missing, empty, or not a recognized * Clerk org role (unknown roles are refused, never defaulted). * * Named to make the already-verified precondition explicit at the * call-site — see CHANGELOG.md 0.4.0 for the naming history — mirroring * `decodeUnverifiedBearer`'s equivalent rename in `./tenancy-domain.ts`. * * @example * ```ts * // session MUST already be verified upstream, e.g.: * // const { orgId, userId, orgRole } = await auth(); // Clerk server-side * const { tenant, subject, role } = normalizeVerifiedHumanSession({ * orgId: "org_abc", * userId: "user_123", * orgRole: "org:admin", * }); * // -> { tenant: "org_abc", subject: "user_123", role: "admin" } * ``` */ export declare function normalizeVerifiedHumanSession(session: ClerkSessionLike | null | undefined): ResolvedHumanIdentity; //# sourceMappingURL=human-path.d.ts.map