/** * @vantageos/cloud-identity 0.2.0 — Domain-tenancy layer. * * Additive-only: does not modify any 0.1.0 exports. * * Provides: * - WorkspaceRole literal union + Zod schema * - Workspace type + Zod schema * - WorkspaceMember type + Zod schema * - TenantContext type + Zod schema * - ScopeViolationError class (code: "SCOPE_VIOLATION") * - getEffectiveTenantId(ctx, args) — multi-tenant isolation guard * - decodeUnverifiedBearer(token) — DECODE-ONLY helper, NOT authentication. * The decoded payload is attacker-controlled. Production code MUST use a * signed JWT or opaque-token lookup before treating the payload as a * trust boundary. */ import { z } from "zod"; export declare const workspaceRoleSchema: z.ZodEnum<{ Admin: "Admin"; Editor: "Editor"; Viewer: "Viewer"; }>; export type WorkspaceRole = z.infer; export declare const workspaceSchema: z.ZodObject<{ id: z.ZodString; name: z.ZodString; createdAt: z.ZodNumber; metadata: z.ZodOptional>; }, z.core.$strip>; export type Workspace = z.infer; export declare const workspaceMemberSchema: z.ZodObject<{ userId: z.ZodString; workspaceId: z.ZodString; role: z.ZodEnum<{ Admin: "Admin"; Editor: "Editor"; Viewer: "Viewer"; }>; joinedAt: z.ZodNumber; }, z.core.$strip>; export type WorkspaceMember = z.infer; export declare const tenantContextSchema: z.ZodObject<{ workspaceId: z.ZodString; userId: z.ZodString; roles: z.ZodArray>; }, z.core.$strip>; export type TenantContext = z.infer; export interface ScopeViolationPayload { requestedTenantId: string; contextTenantId: string; reason: string; } /** * Thrown by `getEffectiveTenantId` when `args.workspaceId` does not match the * workspaceId encoded in the bearer-resolved `TenantContext`. This error is the * canonical cross-tenant isolation signal across the VantagePeers Cloud fleet. * * Callers MUST translate this to a 403 or MCP permission-denied — never 404. */ export declare class ScopeViolationError extends Error { readonly code: "SCOPE_VIOLATION"; readonly payload: ScopeViolationPayload; constructor(payload: ScopeViolationPayload); } /** * Resolve the effective tenant workspace ID from a `TenantContext` + request args. * * If `args.workspaceId` differs from the context's `workspaceId` (derived from * the bearer token), a `ScopeViolationError` is thrown immediately. * * This is the primary multi-tenant isolation gate — call it at the top of every * MCP tool handler that accepts a `workspaceId` argument. * * @example * ```ts * const tenantId = getEffectiveTenantId(ctx, args); * // safe to use tenantId for DB queries — caller's scope is verified * ``` */ export declare function getEffectiveTenantId(ctx: TenantContext, args: { workspaceId: string; }): string; /** * @security ⚠️ DECODE-ONLY. NOT AUTHENTICATION. NOT A TRUST BOUNDARY. * * Decodes a `base64(JSON({ userId, workspaceId, roles[] }))` payload and * validates its SHAPE with Zod. It performs NO signature verification, NO * issuer check, NO expiry check, NO replay-attack protection. The decoded * payload is attacker-controlled and MUST NOT be used as the source of * truth for multi-tenant isolation. * * Forgery example: any attacker producing * base64(JSON({ userId:"x", workspaceId:"victim-org", roles:["Admin"] })) * passes this function. Treating the returned `workspaceId` as authoritative * — for example feeding it into `getEffectiveTenantId` as the trusted * `ctx.workspaceId` — silently grants cross-tenant access. * * Use only as: * - test fixture / harness helper * - decoder for a bearer that was ALREADY verified by an upstream signed-JWT * middleware (the production trust boundary) * * For the production trust boundary, callers MUST substitute a signed JWT * verifier (not yet exported by this package) or an opaque-token lookup * against a Convex tenancy table. * * Renamed from `resolveBearer` (0.2.0 pre-release) to make the lack of * verification impossible to miss at the call-site. */ declare const bearerPayloadSchema: z.ZodObject<{ userId: z.ZodString; workspaceId: z.ZodString; roles: z.ZodArray>; }, z.core.$strip>; export type BearerPayload = z.infer; export declare function decodeUnverifiedBearer(token: string): Promise; export {}; //# sourceMappingURL=tenancy-domain.d.ts.map