/**
 * Tenant Context - Secure Tenant ID Handling
 *
 * Provides branded types and secure context creation to prevent
 * tenant ID injection attacks. Tenant IDs can ONLY be extracted
 * from validated JWT tokens, never from request parameters or body.
 *
 * HIGH SECURITY: Prevents cross-tenant data access vulnerability.
 *
 * @packageDocumentation
 */
import type { FastifyRequest, FastifyReply } from 'fastify';
import { z } from 'zod';
import type { ID } from './types.js';
/**
 * Unique symbol for branding ValidatedTenantId
 * This ensures the type cannot be forged at compile time
 */
declare const TenantIdBrand: unique symbol;
/**
 * A tenant ID that has been validated from a JWT token.
 *
 * This branded type can ONLY be created through:
 * - `createTenantContext()` from a validated JWT
 * - `extractTenantContext()` middleware
 *
 * Raw strings cannot be assigned to this type, preventing
 * accidental use of unvalidated tenant IDs.
 *
 * @example
 * // This will NOT compile:
 * const badId: ValidatedTenantId = "some-tenant-id";
 *
 * // This is the only valid way:
 * const ctx = await extractTenantContext(request);
 * const validId: ValidatedTenantId = ctx.tenantId;
 */
export type ValidatedTenantId = string & {
    readonly [TenantIdBrand]: true;
};
/**
 * Unique symbol for branding ValidatedUserId
 */
declare const UserIdBrand: unique symbol;
/**
 * A user ID that has been validated from a JWT token.
 */
export type ValidatedUserId = string & {
    readonly [UserIdBrand]: true;
};
/**
 * Validated JWT payload structure
 */
export interface ValidatedJwtPayload {
    /** Subject (user ID) - validated from JWT */
    sub: string;
    /** Tenant ID - validated from JWT */
    tid: string;
    /** User roles from JWT */
    roles?: string[];
    /** User permissions from JWT */
    permissions?: string[];
    /** Token issued at timestamp */
    iat: number;
    /** Token expiration timestamp */
    exp: number;
}
/**
 * Zod schema for validating JWT payload for tenant context
 */
export declare const validatedJwtPayloadSchema: z.ZodObject<{
    sub: z.ZodString;
    tid: z.ZodString;
    iat: z.ZodNumber;
    exp: z.ZodNumber;
    roles: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
    permissions: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
}, "strip", z.ZodTypeAny, {
    sub?: string;
    tid?: string;
    iat?: number;
    exp?: number;
    roles?: string[];
    permissions?: string[];
}, {
    sub?: string;
    tid?: string;
    iat?: number;
    exp?: number;
    roles?: string[];
    permissions?: string[];
}>;
/**
 * Immutable tenant context created from validated JWT.
 *
 * This is the ONLY way to safely pass tenant information to services.
 * All service methods should accept TenantContext instead of raw tenantId.
 *
 * Properties are readonly to prevent mutation after creation.
 *
 * @example
 * // Service method signature (SECURE)
 * async createPolicy(ctx: TenantContext, input: CreatePolicyInput): Promise<Policy>
 *
 * // NOT this (VULNERABLE)
 * async createPolicy(tenantId: string, input: CreatePolicyInput): Promise<Policy>
 */
export interface TenantContext {
    /** Validated tenant ID - can only come from JWT */
    readonly tenantId: ValidatedTenantId;
    /** Validated user ID - can only come from JWT */
    readonly userId: ValidatedUserId;
    /** User roles from JWT token */
    readonly roles: readonly string[];
    /** User permissions from JWT token */
    readonly permissions: readonly string[];
    /** Request trace ID for correlation */
    readonly traceId?: string;
    /** Session ID if available */
    readonly sessionId?: string;
    /** Timestamp when context was created */
    readonly createdAt: number;
}
/**
 * Create a TenantContext from a validated JWT payload.
 *
 * This is the ONLY legitimate way to create a TenantContext.
 * The JWT must already be validated (signature verified, not expired).
 *
 * @param jwt - Validated JWT payload (must have passed signature verification)
 * @param options - Additional context options
 * @returns Immutable TenantContext
 *
 * @example
 * // After JWT verification in middleware:
 * const ctx = createTenantContext(validatedJwt, { traceId: request.id });
 * request.tenantContext = ctx;
 */
export declare function createTenantContext(jwt: ValidatedJwtPayload, options?: {
    traceId?: string;
    sessionId?: string;
}): TenantContext;
/**
 * Extend FastifyRequest with tenant context
 */
declare module 'fastify' {
    interface FastifyRequest {
        /**
         * Validated tenant context from JWT.
         * Only available after `requireTenantContext` middleware.
         */
        tenantContext?: TenantContext;
    }
}
/**
 * Extract and validate tenant context from JWT token.
 *
 * This middleware:
 * 1. Extracts the Bearer token from Authorization header
 * 2. Verifies the JWT signature
 * 3. Validates required claims (sub, tid)
 * 4. Creates an immutable TenantContext
 * 5. Attaches it to request.tenantContext
 *
 * SECURITY: Tenant ID is extracted ONLY from the JWT, never from
 * request body, query params, or other user-controlled input.
 *
 * @example
 * // Register as route preHandler
 * fastify.post('/api/v1/policies', {
 *   preHandler: [requireTenantContext],
 * }, async (request, reply) => {
 *   const ctx = request.tenantContext!;
 *   const policy = await policyService.create(ctx, input);
 * });
 */
export declare function requireTenantContext(request: FastifyRequest, reply: FastifyReply): Promise<void>;
/**
 * Get the tenant context from a request, throwing if not available.
 *
 * Use this in route handlers after `requireTenantContext` middleware.
 *
 * @param request - Fastify request
 * @returns TenantContext
 * @throws UnauthorizedError if context is not set
 *
 * @example
 * fastify.get('/policies', {
 *   preHandler: [requireTenantContext],
 * }, async (request) => {
 *   const ctx = getTenantContext(request);
 *   return policyService.list(ctx);
 * });
 */
export declare function getTenantContext(request: FastifyRequest): TenantContext;
/**
 * Check if user has any of the specified roles
 */
export declare function hasRole(ctx: TenantContext, ...roles: string[]): boolean;
/**
 * Check if user has all of the specified permissions
 */
export declare function hasPermission(ctx: TenantContext, ...permissions: string[]): boolean;
/**
 * Check if user has any of the specified permissions
 */
export declare function hasAnyPermission(ctx: TenantContext, ...permissions: string[]): boolean;
/**
 * Check if user is an admin (has admin or super_admin role)
 */
export declare function isAdmin(ctx: TenantContext): boolean;
/**
 * Check if user is a super admin (cross-tenant access)
 */
export declare function isSuperAdmin(ctx: TenantContext): boolean;
/**
 * Create a tenant context for system operations (internal use only).
 *
 * WARNING: This bypasses JWT validation and should ONLY be used for:
 * - Background jobs
 * - Internal service-to-service calls
 * - Scheduled tasks
 *
 * NEVER use this for handling user requests.
 *
 * @internal
 */
export declare function createSystemTenantContext(tenantId: string, options?: {
    userId?: string;
    roles?: string[];
    traceId?: string;
}): TenantContext;
/**
 * Extract raw tenant ID from context for legacy code migration.
 *
 * @deprecated Use TenantContext directly in service methods.
 *             This function exists only for incremental migration.
 *
 * @param ctx - TenantContext
 * @returns Raw tenant ID string
 */
export declare function extractTenantId(ctx: TenantContext): ID;
/**
 * Extract raw user ID from context for legacy code migration.
 *
 * @deprecated Use TenantContext directly in service methods.
 *
 * @param ctx - TenantContext
 * @returns Raw user ID string
 */
export declare function extractUserId(ctx: TenantContext): ID;
export {};
//# sourceMappingURL=tenant-context.d.ts.map