@kysera/rls 0.7.4 → 0.8.0

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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @kysera/rls
2
2
 
3
- > **Row-Level Security Plugin for Kysera (v0.7.3)** - Declarative authorization policies with automatic query transformation through @kysera/executor's Unified Execution Layer and AsyncLocalStorage-based context management.
3
+ > **Row-Level Security Plugin for Kysera** - Declarative authorization policies with automatic query transformation through @kysera/executor's Unified Execution Layer and AsyncLocalStorage-based context management.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@kysera/rls.svg)](https://www.npmjs.com/package/@kysera/rls)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
@@ -150,7 +150,7 @@ The RLS plugin is built on @kysera/executor's Unified Execution Layer, which pro
150
150
  ```typescript
151
151
  {
152
152
  name: '@kysera/rls',
153
- version: '0.7.3',
153
+ version: '0.8.0',
154
154
  priority: 50, // Runs after soft-delete (0), before audit (100)
155
155
  dependencies: [],
156
156
  }
@@ -192,7 +192,7 @@ const posts = await orm.posts.findAll()
192
192
 
193
193
  - SELECT operations: Policies are applied immediately as WHERE clauses
194
194
  - INSERT/UPDATE/DELETE: Marked for validation (actual enforcement in `extendRepository`)
195
- - Skip conditions: `skipTables`, `metadata['skipRLS']`, `requireContext`, system user, bypass roles
195
+ - Skip conditions: `excludeTables`, `metadata['skipRLS']`, `requireContext`, system user, bypass roles
196
196
 
197
197
  #### 2. `extendRepository` - Mutation Enforcement (CREATE/UPDATE/DELETE)
198
198
 
@@ -767,13 +767,9 @@ interface RLSPluginOptions<DB = unknown> {
767
767
 
768
768
  /**
769
769
  * Tables to exclude from RLS (always bypass)
770
- * Replaces deprecated skipTables
771
770
  */
772
771
  excludeTables?: string[]
773
772
 
774
- /** @deprecated Use excludeTables instead */
775
- skipTables?: string[]
776
-
777
773
  /** Roles that bypass RLS entirely */
778
774
  bypassRoles?: string[]
779
775
 
@@ -822,7 +818,7 @@ import { createLogger } from '@kysera/core'
822
818
 
823
819
  const plugin = rlsPlugin({
824
820
  schema: rlsSchema,
825
- skipTables: ['audit_logs', 'migrations'],
821
+ excludeTables: ['audit_logs', 'migrations'],
826
822
  bypassRoles: ['admin', 'system'],
827
823
  logger: createLogger({ level: 'info' }),
828
824
  requireContext: true,
@@ -1151,7 +1147,7 @@ The RLS plugin follows the standard `@kysera/executor` plugin lifecycle:
1151
1147
  **Bypass Mechanisms:**
1152
1148
 
1153
1149
  - System context bypass is immediate (no policy evaluation)
1154
- - `skipTables` bypass is immediate (no policy evaluation)
1150
+ - `excludeTables` bypass is immediate (no policy evaluation)
1155
1151
  - Bypass roles checked before policy evaluation
1156
1152
 
1157
1153
  ### Transaction Support
package/dist/index.d.ts CHANGED
@@ -575,15 +575,9 @@ interface RLSPluginOptions<DB = unknown> {
575
575
  schema: RLSSchema<DB>;
576
576
  /**
577
577
  * Tables to exclude from RLS (always bypass policies)
578
- * Replaces the deprecated `skipTables` option for consistency with other plugins.
579
578
  * @default []
580
579
  */
581
580
  excludeTables?: string[];
582
- /**
583
- * @deprecated Use `excludeTables` instead for consistency with other Kysera plugins
584
- * @default []
585
- */
586
- skipTables?: string[];
587
581
  /** Roles that bypass RLS entirely (e.g., ['admin', 'superuser']) */
588
582
  bypassRoles?: string[];
589
583
  /** Logger instance for RLS operations */
@@ -637,7 +631,6 @@ interface RLSPluginOptions<DB = unknown> {
637
631
  */
638
632
  declare const RLSPluginOptionsSchema: z.ZodObject<{
639
633
  excludeTables: z.ZodOptional<z.ZodArray<z.ZodString>>;
640
- skipTables: z.ZodOptional<z.ZodArray<z.ZodString>>;
641
634
  bypassRoles: z.ZodOptional<z.ZodArray<z.ZodString>>;
642
635
  requireContext: z.ZodOptional<z.ZodBoolean>;
643
636
  allowUnfilteredQueries: z.ZodOptional<z.ZodBoolean>;
package/dist/index.js CHANGED
@@ -1198,8 +1198,6 @@ var RAW_VERSION = "__VERSION__";
1198
1198
  var VERSION = RAW_VERSION.startsWith("__") ? "0.0.0-dev" : RAW_VERSION;
1199
1199
  var RLSPluginOptionsSchema = z.object({
1200
1200
  excludeTables: z.array(z.string()).optional(),
1201
- skipTables: z.array(z.string()).optional(),
1202
- // deprecated but kept for backward compatibility
1203
1201
  bypassRoles: z.array(z.string()).optional(),
1204
1202
  requireContext: z.boolean().optional(),
1205
1203
  allowUnfilteredQueries: z.boolean().optional(),
@@ -1209,8 +1207,7 @@ var RLSPluginOptionsSchema = z.object({
1209
1207
  function rlsPlugin(options) {
1210
1208
  const {
1211
1209
  schema,
1212
- excludeTables: excludeTablesOption,
1213
- skipTables: skipTablesOption,
1210
+ excludeTables = [],
1214
1211
  bypassRoles = [],
1215
1212
  logger = silentLogger,
1216
1213
  requireContext = true,
@@ -1221,12 +1218,6 @@ function rlsPlugin(options) {
1221
1218
  onViolation,
1222
1219
  primaryKeyColumn = "id"
1223
1220
  } = options;
1224
- const excludeTables = excludeTablesOption ?? skipTablesOption ?? [];
1225
- if (skipTablesOption !== void 0 && excludeTablesOption === void 0) {
1226
- logger.warn?.(
1227
- '[RLS] The "skipTables" option is deprecated. Use "excludeTables" instead for consistency with other Kysera plugins.'
1228
- );
1229
- }
1230
1221
  let registry;
1231
1222
  let selectTransformer;
1232
1223
  let mutationGuard;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/policy/schema.ts","../src/policy/builder.ts","../src/policy/registry.ts","../src/context/storage.ts","../src/context/manager.ts","../src/utils/type-utils.ts","../src/transformer/select.ts","../src/transformer/mutation.ts","../src/version.ts","../src/plugin.ts","../src/utils/helpers.ts"],"names":["allow","deny","validate","filter","silentLogger"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * RLS Error Classes\n *\n * This module provides specialized error classes for Row-Level Security operations.\n * All errors extend base error classes from @kysera/core for consistency across\n * the Kysera ecosystem.\n *\n * @module @kysera/rls/errors\n */\n\nimport { DatabaseError } from '@kysera/core'\nimport type { ErrorCode } from '@kysera/core'\n\n// ============================================================================\n// RLS Error Codes\n// ============================================================================\n\n/**\n * RLS-specific error codes\n *\n * These codes extend the unified error codes from @kysera/core with\n * RLS-specific error conditions.\n */\nexport const RLSErrorCodes = {\n /** RLS context is missing or not set */\n RLS_CONTEXT_MISSING: 'RLS_CONTEXT_MISSING' as ErrorCode,\n /** RLS policy violation occurred */\n RLS_POLICY_VIOLATION: 'RLS_POLICY_VIOLATION' as ErrorCode,\n /** RLS policy definition is invalid */\n RLS_POLICY_INVALID: 'RLS_POLICY_INVALID' as ErrorCode,\n /** RLS schema definition is invalid */\n RLS_SCHEMA_INVALID: 'RLS_SCHEMA_INVALID' as ErrorCode,\n /** RLS context validation failed */\n RLS_CONTEXT_INVALID: 'RLS_CONTEXT_INVALID' as ErrorCode,\n /** RLS policy evaluation threw an error */\n RLS_POLICY_EVALUATION_ERROR: 'RLS_POLICY_EVALUATION_ERROR' as ErrorCode\n} as const\n\n/**\n * Type for RLS error codes\n */\nexport type RLSErrorCode = (typeof RLSErrorCodes)[keyof typeof RLSErrorCodes]\n\n// ============================================================================\n// Base RLS Error\n// ============================================================================\n\n/**\n * Base class for all RLS-related errors\n *\n * Extends DatabaseError from @kysera/core for consistency with other Kysera packages.\n * Provides common error functionality including error codes and JSON serialization.\n *\n * @example\n * ```typescript\n * throw new RLSError('Something went wrong', RLSErrorCodes.RLS_POLICY_INVALID);\n * ```\n */\nexport class RLSError extends DatabaseError {\n /**\n * Creates a new RLS error\n *\n * @param message - Error message\n * @param code - RLS error code\n */\n constructor(message: string, code: RLSErrorCode) {\n super(message, code)\n this.name = 'RLSError'\n }\n}\n\n// ============================================================================\n// Context Errors\n// ============================================================================\n\n/**\n * Error thrown when RLS context is missing\n *\n * This error occurs when an operation requiring RLS context is executed\n * outside of a context scope (i.e., without calling withRLSContext()).\n *\n * @example\n * ```typescript\n * // This will throw RLSContextError\n * const result = await db.selectFrom('posts').execute();\n *\n * // Correct usage with context\n * await withRLSContext(rlsContext, async () => {\n * const result = await db.selectFrom('posts').execute();\n * });\n * ```\n */\nexport class RLSContextError extends RLSError {\n /**\n * Creates a new RLS context error\n *\n * @param message - Error message (defaults to standard message)\n */\n constructor(message = 'No RLS context found. Ensure code runs within withRLSContext()') {\n super(message, RLSErrorCodes.RLS_CONTEXT_MISSING)\n this.name = 'RLSContextError'\n }\n}\n\n/**\n * Error thrown when RLS context validation fails\n *\n * Extends RLSError as context validation failures are RLS-specific errors.\n *\n * This error occurs when the provided RLS context is invalid or missing\n * required fields.\n *\n * @example\n * ```typescript\n * // Missing required userId field\n * const invalidContext = {\n * auth: {\n * roles: ['user']\n * // userId is missing!\n * },\n * timestamp: new Date()\n * };\n *\n * // This will throw RLSContextValidationError\n * validateRLSContext(invalidContext);\n * ```\n */\nexport class RLSContextValidationError extends RLSError {\n public readonly field: string\n\n /**\n * Creates a new context validation error\n *\n * @param message - Error message\n * @param field - Field that failed validation\n */\n constructor(message: string, field: string) {\n super(message, RLSErrorCodes.RLS_CONTEXT_INVALID)\n this.name = 'RLSContextValidationError'\n this.field = field\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n field: this.field\n }\n }\n}\n\n// ============================================================================\n// Policy Errors\n// ============================================================================\n\n/**\n * Error thrown when an RLS policy violation occurs\n *\n * This error is thrown when a database operation is denied by RLS policies.\n * It provides detailed information about the violation including the operation,\n * table, and reason for denial.\n *\n * @example\n * ```typescript\n * // User tries to update a post they don't own\n * throw new RLSPolicyViolation(\n * 'update',\n * 'posts',\n * 'User does not own this post',\n * 'ownership_policy'\n * );\n * ```\n */\nexport class RLSPolicyViolation extends RLSError {\n public readonly operation: string\n public readonly table: string\n public readonly reason: string\n public readonly policyName?: string\n\n /**\n * Creates a new policy violation error\n *\n * @param operation - Database operation that was denied (read, create, update, delete)\n * @param table - Table name where violation occurred\n * @param reason - Reason for the policy violation\n * @param policyName - Name of the policy that denied access (optional)\n */\n constructor(operation: string, table: string, reason: string, policyName?: string) {\n super(\n `RLS policy violation: ${operation} on ${table} - ${reason}`,\n RLSErrorCodes.RLS_POLICY_VIOLATION\n )\n this.name = 'RLSPolicyViolation'\n this.operation = operation\n this.table = table\n this.reason = reason\n if (policyName !== undefined) {\n this.policyName = policyName\n }\n }\n\n override toJSON(): Record<string, unknown> {\n const json: Record<string, unknown> = {\n ...super.toJSON(),\n operation: this.operation,\n table: this.table,\n reason: this.reason\n }\n if (this.policyName !== undefined) {\n json['policyName'] = this.policyName\n }\n return json\n }\n}\n\n// ============================================================================\n// Policy Evaluation Errors\n// ============================================================================\n\n/**\n * Error thrown when a policy condition throws an error during evaluation\n *\n * This error is distinct from RLSPolicyViolation - it indicates a bug in the\n * policy condition function itself, not a legitimate access denial.\n *\n * @example\n * ```typescript\n * // A policy with a bug\n * allow('read', ctx => {\n * return ctx.row.someField.value; // Throws if someField is undefined\n * });\n *\n * // This will throw RLSPolicyEvaluationError, not RLSPolicyViolation\n * ```\n */\nexport class RLSPolicyEvaluationError extends RLSError {\n public readonly operation: string\n public readonly table: string\n public readonly policyName?: string\n public readonly originalError?: Error\n\n /**\n * Creates a new policy evaluation error\n *\n * @param operation - Database operation being performed\n * @param table - Table name where error occurred\n * @param message - Error message from the policy\n * @param policyName - Name of the policy that threw\n * @param originalError - The original error thrown by the policy\n */\n constructor(\n operation: string,\n table: string,\n message: string,\n policyName?: string,\n originalError?: Error\n ) {\n super(\n `RLS policy evaluation error during ${operation} on ${table}: ${message}`,\n RLSErrorCodes.RLS_POLICY_EVALUATION_ERROR\n )\n this.name = 'RLSPolicyEvaluationError'\n this.operation = operation\n this.table = table\n if (policyName !== undefined) {\n this.policyName = policyName\n }\n if (originalError !== undefined) {\n this.originalError = originalError\n // Preserve the original stack trace for debugging\n if (originalError.stack) {\n this.stack = `${this.stack}\\n\\nCaused by:\\n${originalError.stack}`\n }\n }\n }\n\n override toJSON(): Record<string, unknown> {\n const json: Record<string, unknown> = {\n ...super.toJSON(),\n operation: this.operation,\n table: this.table\n }\n if (this.policyName !== undefined) {\n json['policyName'] = this.policyName\n }\n if (this.originalError !== undefined) {\n json['originalError'] = {\n name: this.originalError.name,\n message: this.originalError.message\n }\n }\n return json\n }\n}\n\n// ============================================================================\n// Schema Errors\n// ============================================================================\n\n/**\n * Error thrown when RLS schema validation fails\n *\n * Extends RLSError as schema validation failures are RLS-specific errors.\n *\n * This error occurs when the RLS schema definition is invalid or contains\n * configuration errors.\n *\n * @example\n * ```typescript\n * // Invalid policy definition\n * const invalidSchema = {\n * posts: {\n * policies: [\n * {\n * type: 'invalid-type', // Invalid policy type!\n * operation: 'read',\n * condition: (ctx) => true\n * }\n * ]\n * }\n * };\n *\n * // This will throw RLSSchemaError\n * validateRLSSchema(invalidSchema);\n * ```\n */\nexport class RLSSchemaError extends RLSError {\n public readonly details: Record<string, unknown>\n\n /**\n * Creates a new schema validation error\n *\n * @param message - Error message\n * @param details - Additional details about the validation failure\n */\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(message, RLSErrorCodes.RLS_SCHEMA_INVALID)\n this.name = 'RLSSchemaError'\n this.details = details\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n details: this.details\n }\n }\n}\n","/**\n * RLS schema definition and validation\n *\n * Provides functions to define, validate, and merge RLS schemas.\n */\n\nimport type { RLSSchema, TableRLSConfig, PolicyDefinition } from './types.js'\nimport { RLSSchemaError } from '../errors.js'\n\n/**\n * Define RLS schema with full type safety\n *\n * @example\n * ```typescript\n * interface Database {\n * users: { id: number; email: string; tenant_id: number };\n * posts: { id: number; user_id: number; tenant_id: number };\n * }\n *\n * const schema = defineRLSSchema<Database>({\n * users: {\n * policies: [\n * // Users can read their own records\n * allow('read', ctx => ctx.auth.userId === ctx.row.id),\n * // Filter by tenant\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId })),\n * // Admins bypass all checks\n * allow('all', ctx => ctx.auth.roles.includes('admin')),\n * ],\n * },\n * posts: {\n * policies: [\n * // Filter posts by tenant\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId })),\n * // Users can only edit their own posts\n * allow(['update', 'delete'], ctx => ctx.auth.userId === ctx.row.user_id),\n * // Validate new posts belong to user's tenant\n * validate('create', ctx => ctx.data.tenant_id === ctx.auth.tenantId),\n * ],\n * defaultDeny: true, // Require explicit allow\n * },\n * });\n * ```\n */\nexport function defineRLSSchema<DB>(schema: RLSSchema<DB>): RLSSchema<DB> {\n // Validate schema\n validateSchema(schema)\n return schema\n}\n\n/**\n * Validate RLS schema\n * Throws RLSSchemaError if validation fails\n *\n * @internal\n */\nfunction validateSchema<DB>(schema: RLSSchema<DB>): void {\n for (const [table, config] of Object.entries(schema)) {\n if (!config) continue\n\n const tableConfig = config as TableRLSConfig\n\n if (!Array.isArray(tableConfig.policies)) {\n throw new RLSSchemaError(`Invalid policies for table \"${table}\": must be an array`, { table })\n }\n\n // Validate each policy\n for (let i = 0; i < tableConfig.policies.length; i++) {\n const policy = tableConfig.policies[i]\n if (policy !== undefined) {\n validatePolicy(policy, table, i)\n }\n }\n\n // Validate skipFor if present (array of role names that bypass RLS)\n if (tableConfig.skipFor !== undefined) {\n if (!Array.isArray(tableConfig.skipFor)) {\n throw new RLSSchemaError(\n `Invalid skipFor for table \"${table}\": must be an array of role names`,\n { table }\n )\n }\n\n // skipFor contains role names (strings), not operations\n for (const role of tableConfig.skipFor) {\n if (typeof role !== 'string' || role.trim() === '') {\n throw new RLSSchemaError(\n `Invalid role in skipFor for table \"${table}\": must be a non-empty string`,\n { table }\n )\n }\n }\n }\n\n // Validate defaultDeny if present\n if (tableConfig.defaultDeny !== undefined && typeof tableConfig.defaultDeny !== 'boolean') {\n throw new RLSSchemaError(`Invalid defaultDeny for table \"${table}\": must be a boolean`, {\n table\n })\n }\n }\n}\n\n/**\n * Validate a single policy\n * Throws RLSSchemaError if validation fails\n *\n * @internal\n */\nfunction validatePolicy(policy: PolicyDefinition, table: string, index: number): void {\n if (!policy.type) {\n throw new RLSSchemaError(`Policy ${index} for table \"${table}\" missing type`, { table, index })\n }\n\n const validTypes = ['allow', 'deny', 'filter', 'validate']\n if (!validTypes.includes(policy.type)) {\n throw new RLSSchemaError(\n `Policy ${index} for table \"${table}\" has invalid type: ${policy.type}`,\n { table, index, type: policy.type }\n )\n }\n\n if (!policy.operation) {\n throw new RLSSchemaError(`Policy ${index} for table \"${table}\" missing operation`, {\n table,\n index\n })\n }\n\n const validOps = ['read', 'create', 'update', 'delete', 'all']\n const ops = Array.isArray(policy.operation) ? policy.operation : [policy.operation]\n\n for (const op of ops) {\n if (!validOps.includes(op)) {\n throw new RLSSchemaError(\n `Policy ${index} for table \"${table}\" has invalid operation: ${op}`,\n { table, index, operation: op }\n )\n }\n }\n\n if (policy.condition === undefined || policy.condition === null) {\n throw new RLSSchemaError(`Policy ${index} for table \"${table}\" missing condition`, {\n table,\n index\n })\n }\n\n if (typeof policy.condition !== 'function' && typeof policy.condition !== 'string') {\n throw new RLSSchemaError(\n `Policy ${index} for table \"${table}\" condition must be a function or string`,\n { table, index }\n )\n }\n\n // Validate priority if present\n if (policy.priority !== undefined && typeof policy.priority !== 'number') {\n throw new RLSSchemaError(`Policy ${index} for table \"${table}\" priority must be a number`, {\n table,\n index\n })\n }\n\n // Validate name if present\n if (policy.name !== undefined && typeof policy.name !== 'string') {\n throw new RLSSchemaError(`Policy ${index} for table \"${table}\" name must be a string`, {\n table,\n index\n })\n }\n}\n\n/**\n * Merge multiple RLS schemas\n * Later schemas override earlier ones for the same table\n *\n * @example\n * ```typescript\n * const baseSchema = defineRLSSchema<Database>({\n * users: {\n * policies: [\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId })),\n * ],\n * },\n * });\n *\n * const adminSchema = defineRLSSchema<Database>({\n * users: {\n * policies: [\n * allow('all', ctx => ctx.auth.roles.includes('admin')),\n * ],\n * },\n * });\n *\n * // Merged schema will have both filters and admin allow\n * const merged = mergeRLSSchemas(baseSchema, adminSchema);\n * ```\n */\nexport function mergeRLSSchemas<DB>(...schemas: RLSSchema<DB>[]): RLSSchema<DB> {\n const merged: RLSSchema<DB> = {}\n\n for (const schema of schemas) {\n for (const [table, config] of Object.entries(schema)) {\n if (!config) continue\n\n const existingConfig = merged[table as keyof DB]\n const newConfig = config as TableRLSConfig\n\n if (existingConfig) {\n // Merge policies (append new policies)\n existingConfig.policies = [...existingConfig.policies, ...newConfig.policies]\n\n // Merge skipFor (combine arrays and deduplicate)\n if (newConfig.skipFor) {\n const existingSkipFor = existingConfig.skipFor ?? []\n const combinedSkipFor = [...existingSkipFor, ...newConfig.skipFor]\n existingConfig.skipFor = Array.from(new Set(combinedSkipFor))\n }\n\n // Override defaultDeny if explicitly set in new config\n if (newConfig.defaultDeny !== undefined) {\n existingConfig.defaultDeny = newConfig.defaultDeny\n }\n } else {\n // Deep copy the config to avoid mutation\n // Type cast necessary: TypeScript cannot infer that the spread object matches\n // the TableRLSConfig type exactly due to optional properties and type narrowing.\n // Runtime safety: We've validated the schema structure via validateSchema(),\n // and we're creating a proper TableRLSConfig from validated components.\n\n merged[table as keyof DB] = {\n policies: [...newConfig.policies],\n skipFor: newConfig.skipFor ? [...newConfig.skipFor] : undefined,\n defaultDeny: newConfig.defaultDeny\n } as TableRLSConfig\n }\n }\n }\n\n // Validate merged schema\n validateSchema(merged)\n\n return merged\n}\n","/**\n * Fluent policy builders for Row-Level Security\n *\n * Provides intuitive builder functions for creating RLS policies:\n * - allow: Grants access when condition is true\n * - deny: Blocks access when condition is true (overrides allow)\n * - filter: Adds WHERE conditions to SELECT queries\n * - validate: Validates mutation data before execution\n */\n\nimport type {\n Operation,\n PolicyDefinition,\n PolicyCondition,\n FilterCondition,\n PolicyHints\n} from './types.js'\n\n/**\n * Options for policy definitions\n */\nexport interface PolicyOptions {\n /** Policy name for debugging and identification */\n name?: string\n /** Priority (higher runs first, deny policies default to 100) */\n priority?: number\n /** Performance optimization hints */\n hints?: PolicyHints\n}\n\n/**\n * Create an allow policy\n * Grants access when condition evaluates to true\n *\n * @example\n * ```typescript\n * // Allow users to read their own records\n * allow('read', ctx => ctx.auth.userId === ctx.row.userId)\n *\n * // Allow admins to do everything\n * allow('all', ctx => ctx.auth.roles.includes('admin'))\n *\n * // Allow with multiple operations\n * allow(['read', 'update'], ctx => ctx.auth.userId === ctx.row.userId)\n *\n * // Named policy with priority\n * allow('read', ctx => ctx.auth.roles.includes('verified'), {\n * name: 'verified-users-only',\n * priority: 10\n * })\n * ```\n */\nexport function allow(\n operation: Operation | Operation[],\n condition: PolicyCondition,\n options?: PolicyOptions\n): PolicyDefinition {\n const policy: PolicyDefinition = {\n type: 'allow',\n operation,\n condition: condition,\n priority: options?.priority ?? 0\n }\n\n if (options?.name !== undefined) {\n policy.name = options.name\n }\n\n if (options?.hints !== undefined) {\n policy.hints = options.hints\n }\n\n return policy\n}\n\n/**\n * Create a deny policy\n * Blocks access when condition evaluates to true (overrides allow)\n * If no condition is provided, always denies\n *\n * @example\n * ```typescript\n * // Deny access to banned users\n * deny('all', ctx => ctx.auth.attributes?.banned === true)\n *\n * // Deny deletions on archived records\n * deny('delete', ctx => ctx.row.archived === true)\n *\n * // Deny all access to sensitive table\n * deny('all')\n *\n * // Named deny with high priority\n * deny('all', ctx => ctx.auth.attributes?.suspended === true, {\n * name: 'block-suspended-users',\n * priority: 200\n * })\n * ```\n */\nexport function deny(\n operation: Operation | Operation[],\n condition?: PolicyCondition,\n options?: PolicyOptions\n): PolicyDefinition {\n const policy: PolicyDefinition = {\n type: 'deny',\n operation,\n condition: condition ?? (() => true),\n priority: options?.priority ?? 100 // Deny policies run first by default\n }\n\n if (options?.name !== undefined) {\n policy.name = options.name\n }\n\n if (options?.hints !== undefined) {\n policy.hints = options.hints\n }\n\n return policy\n}\n\n/**\n * Create a filter policy\n * Adds WHERE conditions to SELECT queries\n *\n * **IMPORTANT**: Filter conditions must be synchronous functions.\n * Async filter policies are not currently supported because filters are applied\n * directly to query builders at query construction time.\n *\n * @example\n * ```typescript\n * // ✅ CORRECT: Filter by tenant (synchronous)\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId }))\n *\n * // ✅ CORRECT: Filter by organization with soft delete\n * filter('read', ctx => ({\n * organization_id: ctx.auth.organizationIds?.[0],\n * deleted_at: null\n * }))\n *\n * // ❌ WRONG: Async filter (not supported)\n * // filter('read', async ctx => {\n * // const tenantId = await fetchTenantId(ctx.auth.userId)\n * // return { tenant_id: tenantId }\n * // })\n *\n * // ✅ WORKAROUND: Fetch data before creating context\n * // const tenantId = await fetchTenantId(userId)\n * // const ctx = createRLSContext({ auth: { userId, tenantId, roles: [] } })\n * // filter('read', ctx => ({ tenant_id: ctx.auth.tenantId }))\n *\n * // Named filter\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId }), {\n * name: 'tenant-filter'\n * })\n * ```\n */\nexport function filter(\n operation: 'read' | 'all',\n condition: FilterCondition,\n options?: PolicyOptions\n): PolicyDefinition {\n const policy: PolicyDefinition = {\n type: 'filter',\n operation: operation === 'all' ? 'read' : operation,\n condition: condition as unknown as PolicyCondition,\n priority: options?.priority ?? 0\n }\n\n if (options?.name !== undefined) {\n policy.name = options.name\n }\n\n if (options?.hints !== undefined) {\n policy.hints = options.hints\n }\n\n return policy\n}\n\n/**\n * Create a validate policy\n * Validates mutation data before execution\n *\n * @example\n * ```typescript\n * // Validate user can only set their own user_id\n * validate('create', ctx => ctx.data.userId === ctx.auth.userId)\n *\n * // Validate status transitions\n * validate('update', ctx => {\n * const { status } = ctx.data;\n * return !status || ['draft', 'published'].includes(status);\n * })\n *\n * // Apply to both create and update\n * validate('all', ctx => ctx.data.price >= 0)\n *\n * // Named validation\n * validate('create', ctx => validateEmail(ctx.data.email), {\n * name: 'validate-email'\n * })\n * ```\n */\nexport function validate(\n operation: 'create' | 'update' | 'all',\n condition: PolicyCondition,\n options?: PolicyOptions\n): PolicyDefinition {\n const ops: Operation[] = operation === 'all' ? ['create', 'update'] : [operation]\n\n const policy: PolicyDefinition = {\n type: 'validate',\n operation: ops,\n condition: condition,\n priority: options?.priority ?? 0\n }\n\n if (options?.name !== undefined) {\n policy.name = options.name\n }\n\n if (options?.hints !== undefined) {\n policy.hints = options.hints\n }\n\n return policy\n}\n","/**\n * Policy Registry\n * Central registry for managing RLS policies across all tables\n *\n * The PolicyRegistry compiles and stores RLS policies for efficient runtime lookup.\n * It categorizes policies by type (allow/deny/filter/validate) and operation,\n * and provides methods to query policies for specific tables and operations.\n */\n\nimport type {\n Operation,\n PolicyDefinition,\n FilterCondition,\n RLSSchema,\n TableRLSConfig,\n CompiledPolicy,\n CompiledFilterPolicy,\n PolicyEvaluationContext\n} from './types.js'\nimport { RLSSchemaError } from '../errors.js'\nimport { silentLogger, type KyseraLogger } from '@kysera/core'\n\n/**\n * Internal compiled policy with operations as Set for efficient lookup\n */\ninterface InternalCompiledPolicy {\n name: string\n operations: Set<Operation>\n type: 'allow' | 'deny' | 'validate'\n evaluate: (ctx: PolicyEvaluationContext) => boolean | Promise<boolean>\n priority: number\n}\n\n/**\n * Table policy configuration\n */\ninterface TablePolicyConfig {\n allows: InternalCompiledPolicy[]\n denies: InternalCompiledPolicy[]\n filters: CompiledFilterPolicy[]\n validates: InternalCompiledPolicy[]\n skipFor: string[] // Role names that bypass RLS\n defaultDeny: boolean\n}\n\n/**\n * Policy Registry\n * Manages and provides access to RLS policies\n */\nexport class PolicyRegistry<DB = unknown> {\n private tables = new Map<string, TablePolicyConfig>()\n private compiled = false\n private logger: KyseraLogger\n\n constructor(schema?: RLSSchema<DB>, options?: { logger?: KyseraLogger }) {\n this.logger = options?.logger ?? silentLogger\n if (schema) {\n this.loadSchema(schema)\n }\n }\n\n /**\n * Load and compile policies from schema\n *\n * @example\n * ```typescript\n * const registry = new PolicyRegistry<Database>();\n * registry.loadSchema({\n * users: {\n * policies: [\n * allow('read', ctx => ctx.auth.userId === ctx.row.id),\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId })),\n * ],\n * defaultDeny: true,\n * },\n * });\n * ```\n */\n loadSchema(schema: RLSSchema<DB>): void {\n for (const [table, config] of Object.entries(schema)) {\n if (!config) continue\n this.registerTable(table, config as TableRLSConfig)\n }\n this.compiled = true\n }\n\n /**\n * Register policies for a single table\n *\n * @param table - Table name\n * @param config - Table RLS configuration\n */\n registerTable(table: string, config: TableRLSConfig): void {\n const tableConfig: TablePolicyConfig = {\n allows: [],\n denies: [],\n filters: [],\n validates: [],\n skipFor: config.skipFor ?? [],\n defaultDeny: config.defaultDeny ?? true\n }\n\n // Compile and categorize policies\n for (let i = 0; i < config.policies.length; i++) {\n const policy = config.policies[i]\n if (!policy) continue\n\n const policyName = policy.name ?? `${table}_policy_${i}`\n\n try {\n if (policy.type === 'filter') {\n const compiled = this.compileFilterPolicy(policy, policyName)\n tableConfig.filters.push(compiled)\n } else {\n const compiled = this.compilePolicy(policy, policyName)\n\n switch (policy.type) {\n case 'allow':\n tableConfig.allows.push(compiled)\n break\n case 'deny':\n tableConfig.denies.push(compiled)\n break\n case 'validate':\n tableConfig.validates.push(compiled)\n break\n }\n }\n } catch (error) {\n throw new RLSSchemaError(\n `Failed to compile policy \"${policyName}\" for table \"${table}\": ${error instanceof Error ? error.message : String(error)}`,\n { table, policy: policyName }\n )\n }\n }\n\n // Sort by priority (higher priority first)\n tableConfig.allows.sort((a, b) => b.priority - a.priority)\n tableConfig.denies.sort((a, b) => b.priority - a.priority)\n tableConfig.validates.sort((a, b) => b.priority - a.priority)\n\n this.tables.set(table, tableConfig)\n }\n\n /**\n * Register policies - supports both schema and table-based registration\n *\n * @overload Register a full schema\n * @overload Register policies for a single table (deprecated)\n */\n register(schemaOrTable: RLSSchema<DB>): void\n register(\n schemaOrTable: keyof DB & string,\n policies: PolicyDefinition[],\n options?: {\n skipFor?: string[]\n defaultDeny?: boolean\n }\n ): void\n register(\n schemaOrTable: RLSSchema<DB> | (keyof DB & string),\n policies?: PolicyDefinition[],\n options?: {\n skipFor?: string[] // Role names that bypass RLS\n defaultDeny?: boolean\n }\n ): void {\n // If first argument is an object with policies, treat as schema\n if (typeof schemaOrTable === 'object' && schemaOrTable !== null) {\n this.loadSchema(schemaOrTable)\n return\n }\n\n // Otherwise, treat as table-based registration\n const table = schemaOrTable\n if (!policies) {\n throw new RLSSchemaError('Policies are required when registering by table name', { table })\n }\n\n const config: TableRLSConfig = {\n policies\n }\n\n if (options?.skipFor !== undefined) {\n config.skipFor = options.skipFor\n }\n\n if (options?.defaultDeny !== undefined) {\n config.defaultDeny = options.defaultDeny\n }\n\n this.registerTable(table, config)\n }\n\n /**\n * Compile a policy definition into an internal compiled policy\n *\n * @param policy - Policy definition to compile\n * @param name - Policy name for debugging\n * @returns Compiled policy ready for evaluation\n */\n private compilePolicy(policy: PolicyDefinition, name: string): InternalCompiledPolicy {\n const operations = Array.isArray(policy.operation) ? policy.operation : [policy.operation]\n\n // Expand 'all' to all operations\n const expandedOps = operations.flatMap(op =>\n op === 'all' ? (['read', 'create', 'update', 'delete'] as const) : [op]\n ) as Operation[]\n\n return {\n name,\n operations: new Set(expandedOps),\n type: policy.type as 'allow' | 'deny' | 'validate',\n evaluate: policy.condition as (ctx: PolicyEvaluationContext) => boolean | Promise<boolean>,\n priority: policy.priority ?? (policy.type === 'deny' ? 100 : 0)\n }\n }\n\n /**\n * Compile a filter policy\n *\n * @param policy - Filter policy definition\n * @param name - Policy name for debugging\n * @returns Compiled filter policy\n */\n private compileFilterPolicy(policy: PolicyDefinition, name: string): CompiledFilterPolicy {\n const condition = policy.condition as unknown as FilterCondition\n\n return {\n operation: 'read',\n getConditions: condition as (ctx: PolicyEvaluationContext) => Record<string, unknown>,\n name\n }\n }\n\n /**\n * Convert internal compiled policy to public CompiledPolicy\n */\n private toCompiledPolicy(internal: InternalCompiledPolicy): CompiledPolicy {\n return {\n name: internal.name,\n type: internal.type,\n operation: Array.from(internal.operations),\n evaluate: internal.evaluate,\n priority: internal.priority\n }\n }\n\n /**\n * Get allow policies for a table and operation\n */\n getAllows(table: string, operation: Operation): CompiledPolicy[] {\n const config = this.tables.get(table)\n if (!config) return []\n\n return config.allows.filter(p => p.operations.has(operation)).map(p => this.toCompiledPolicy(p))\n }\n\n /**\n * Get deny policies for a table and operation\n */\n getDenies(table: string, operation: Operation): CompiledPolicy[] {\n const config = this.tables.get(table)\n if (!config) return []\n\n return config.denies.filter(p => p.operations.has(operation)).map(p => this.toCompiledPolicy(p))\n }\n\n /**\n * Get validate policies for a table and operation\n */\n getValidates(table: string, operation: Operation): CompiledPolicy[] {\n const config = this.tables.get(table)\n if (!config) return []\n\n return config.validates\n .filter(p => p.operations.has(operation))\n .map(p => this.toCompiledPolicy(p))\n }\n\n /**\n * Get filter policies for a table\n */\n getFilters(table: string): CompiledFilterPolicy[] {\n const config = this.tables.get(table)\n return config?.filters ?? []\n }\n\n /**\n * Get roles that skip RLS for a table\n */\n getSkipFor(table: string): string[] {\n const config = this.tables.get(table)\n return config?.skipFor ?? []\n }\n\n /**\n * Check if table has default deny\n */\n hasDefaultDeny(table: string): boolean {\n const config = this.tables.get(table)\n return config?.defaultDeny ?? true\n }\n\n /**\n * Check if a table is registered\n */\n hasTable(table: string): boolean {\n return this.tables.has(table)\n }\n\n /**\n * Get all registered table names\n */\n getTables(): string[] {\n return Array.from(this.tables.keys())\n }\n\n /**\n * Check if registry is compiled\n */\n isCompiled(): boolean {\n return this.compiled\n }\n\n /**\n * Validate that all policies are properly defined\n *\n * This method checks for common issues:\n * - Tables with no policies and defaultDeny=false (warns)\n * - Tables with skipFor operations but no corresponding policies\n */\n validate(): void {\n for (const [table, config] of this.tables) {\n // Check that at least one operation has policies\n const hasPolicy =\n config.allows.length > 0 ||\n config.denies.length > 0 ||\n config.filters.length > 0 ||\n config.validates.length > 0\n\n if (!hasPolicy && !config.defaultDeny) {\n // Warning: table has no policies and defaultDeny is false\n this.logger.warn?.(\n `[RLS] Table \"${table}\" has no policies and defaultDeny is false. ` +\n `All operations will be allowed.`\n )\n }\n\n // Warn if skipFor includes operations that have policies\n if (config.skipFor.length > 0) {\n const opsWithPolicies = new Set<Operation>()\n\n for (const allow of config.allows) {\n allow.operations.forEach(op => opsWithPolicies.add(op))\n }\n for (const deny of config.denies) {\n deny.operations.forEach(op => opsWithPolicies.add(op))\n }\n for (const validate of config.validates) {\n validate.operations.forEach(op => opsWithPolicies.add(op))\n }\n if (config.filters.length > 0) {\n opsWithPolicies.add('read')\n }\n\n const skippedOpsWithPolicies = config.skipFor.filter(op => {\n // 'all' means skip all operations\n if (op === 'all') return opsWithPolicies.size > 0\n // Check if this is an operation name (for backwards compatibility)\n return opsWithPolicies.has(op as Operation)\n })\n\n if (skippedOpsWithPolicies.length > 0) {\n this.logger.warn?.(\n `[RLS] Table \"${table}\" has skipFor operations that also have policies: ${skippedOpsWithPolicies.join(', ')}. ` +\n `The policies will be ignored for these operations.`\n )\n }\n }\n }\n }\n\n /**\n * Clear all policies\n */\n clear(): void {\n this.tables.clear()\n this.compiled = false\n }\n\n /**\n * Remove policies for a specific table\n */\n remove(table: string): void {\n this.tables.delete(table)\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { RLSContext } from './types.js'\n\n/**\n * AsyncLocalStorage instance for RLS context\n * Provides automatic context propagation across async boundaries\n */\nexport const rlsStorage = new AsyncLocalStorage<RLSContext>()\n","import { rlsStorage } from './storage.js'\nimport type { RLSContext, RLSAuthContext, RLSRequestContext } from './types.js'\nimport { RLSContextError, RLSContextValidationError } from '../errors.js'\n\n/**\n * Options for creating RLS context\n */\nexport interface CreateRLSContextOptions<TUser = unknown, TMeta = unknown> {\n auth: RLSAuthContext<TUser>\n request?: Partial<RLSRequestContext>\n meta?: TMeta\n}\n\n/**\n * Create a new RLS context\n */\nexport function createRLSContext<TUser = unknown, TMeta = unknown>(\n options: CreateRLSContextOptions<TUser, TMeta>\n): RLSContext<TUser, TMeta> {\n validateAuthContext(options.auth)\n\n const context: RLSContext<TUser, TMeta> = {\n auth: {\n ...options.auth,\n isSystem: options.auth.isSystem ?? false // Default to false if not provided\n },\n timestamp: new Date()\n }\n\n if (options.request) {\n context.request = {\n ...options.request,\n timestamp: options.request.timestamp ?? new Date()\n } as RLSRequestContext\n }\n\n if (options.meta !== undefined) {\n context.meta = options.meta\n }\n\n return context\n}\n\n/**\n * Validate auth context\n */\nfunction validateAuthContext(auth: RLSAuthContext): void {\n if (auth.userId === undefined || auth.userId === null) {\n throw new RLSContextValidationError('userId is required in auth context', 'userId')\n }\n\n if (!Array.isArray(auth.roles)) {\n throw new RLSContextValidationError('roles must be an array', 'roles')\n }\n}\n\n/**\n * RLS Context Manager\n * Manages RLS context using AsyncLocalStorage for automatic propagation\n */\nclass RLSContextManager {\n /**\n * Run a synchronous function within an RLS context\n */\n run<T>(context: RLSContext, fn: () => T): T {\n return rlsStorage.run(context, fn)\n }\n\n /**\n * Run an async function within an RLS context\n */\n async runAsync<T>(context: RLSContext, fn: () => Promise<T>): Promise<T> {\n return await rlsStorage.run(context, fn)\n }\n\n /**\n * Get current RLS context\n * @throws RLSContextError if no context is set\n */\n getContext(): RLSContext {\n const ctx = rlsStorage.getStore()\n if (!ctx) {\n throw new RLSContextError()\n }\n return ctx\n }\n\n /**\n * Get current RLS context or null if not set\n */\n getContextOrNull(): RLSContext | null {\n return rlsStorage.getStore() ?? null\n }\n\n /**\n * Check if running within RLS context\n */\n hasContext(): boolean {\n return rlsStorage.getStore() !== undefined\n }\n\n /**\n * Get current auth context\n * @throws RLSContextError if no context is set\n */\n getAuth(): RLSAuthContext {\n return this.getContext().auth\n }\n\n /**\n * Get current user ID\n * @throws RLSContextError if no context is set\n */\n getUserId(): string | number {\n return this.getAuth().userId\n }\n\n /**\n * Get current tenant ID\n * @throws RLSContextError if no context is set\n */\n getTenantId(): string | number | undefined {\n return this.getAuth().tenantId\n }\n\n /**\n * Check if current user has a specific role\n */\n hasRole(role: string): boolean {\n const ctx = this.getContextOrNull()\n return ctx?.auth.roles.includes(role) ?? false\n }\n\n /**\n * Check if current user has a specific permission\n */\n hasPermission(permission: string): boolean {\n const ctx = this.getContextOrNull()\n return ctx?.auth.permissions?.includes(permission) ?? false\n }\n\n /**\n * Check if current context is a system context (bypasses RLS)\n */\n isSystem(): boolean {\n const ctx = this.getContextOrNull()\n return ctx?.auth.isSystem ?? false\n }\n\n /**\n * Create a system context for operations that should bypass RLS\n */\n asSystem<T>(fn: () => T): T {\n const currentCtx = this.getContextOrNull()\n if (!currentCtx) {\n throw new RLSContextError('Cannot create system context without existing context')\n }\n\n const systemCtx: RLSContext = {\n ...currentCtx,\n auth: { ...currentCtx.auth, isSystem: true }\n }\n\n return this.run(systemCtx, fn)\n }\n\n /**\n * Create a system context for async operations\n */\n async asSystemAsync<T>(fn: () => Promise<T>): Promise<T> {\n const currentCtx = this.getContextOrNull()\n if (!currentCtx) {\n throw new RLSContextError('Cannot create system context without existing context')\n }\n\n const systemCtx: RLSContext = {\n ...currentCtx,\n auth: { ...currentCtx.auth, isSystem: true }\n }\n\n return await this.runAsync(systemCtx, fn)\n }\n}\n\n// Export singleton instance\nexport const rlsContext = new RLSContextManager()\n\n/**\n * Convenience function to run code within RLS context\n */\nexport function withRLSContext<T>(context: RLSContext, fn: () => T): T {\n return rlsContext.run(context, fn)\n}\n\n/**\n * Convenience function to run async code within RLS context\n */\nexport async function withRLSContextAsync<T>(\n context: RLSContext,\n fn: () => Promise<T>\n): Promise<T> {\n return await rlsContext.runAsync(context, fn)\n}\n","/**\n * Type utilities for RLS plugin\n *\n * These utilities provide type-safe wrappers around dynamic operations\n * that require runtime flexibility beyond TypeScript's compile-time constraints.\n *\n * NOTE: This file intentionally uses `any` types to bridge the gap between\n * Kysely's compile-time type system and RLS's runtime dynamic requirements.\n * All `any` usage is documented and justified with runtime safety guarantees.\n *\n * @module @kysera/rls/utils/type-utils\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { SelectQueryBuilder, Kysely, RawBuilder } from 'kysely'\nimport { sql } from 'kysely'\n\n/**\n * Type-safe wrapper for dynamic column references in WHERE clauses\n *\n * Kysely's type system requires compile-time known column names, but RLS policies\n * work with dynamic column names at runtime. This utility provides a type-safe\n * boundary for this conversion.\n *\n * Type safety is maintained through:\n * 1. Column names come from validated policy definitions (developer-controlled)\n * 2. Values are type-checked by policy condition functions\n * 3. Runtime validation during policy registration\n *\n * @param table - Table name (from validated policy schema)\n * @param column - Column name (from validated policy definition)\n * @returns Type-safe column reference for Kysely query builder\n */\nexport function createQualifiedColumn(table: string, column: string): string {\n return `${table}.${column}`\n}\n\n/**\n * Type-safe wrapper for applying WHERE conditions from RLS filters\n *\n * This function encapsulates the type boundary between runtime policy conditions\n * and Kysely's compile-time type system.\n *\n * @param qb - Query builder to modify\n * @param column - Qualified column name (table.column)\n * @param operator - Comparison operator\n * @param value - Value to compare against\n * @returns Modified query builder\n */\nexport function applyWhereCondition<DB, TB extends keyof DB & string, O>(\n qb: SelectQueryBuilder<DB, TB, O>,\n column: string,\n operator: 'is' | '=' | 'in',\n value: unknown\n): SelectQueryBuilder<DB, TB, O> {\n return qb.where(column as any, operator as any, value as any)\n}\n\n/**\n * Type-safe wrapper for raw SQL expressions\n *\n * @param expression - SQL expression (e.g., 'FALSE' for impossible conditions)\n * @returns Type-safe raw builder for WHERE clauses\n */\nexport function createRawCondition(expression: string): RawBuilder<boolean> {\n return sql`${sql.raw(expression)}`\n}\n\n/**\n * Type-safe wrapper for dynamic table queries (used in raw db queries)\n *\n * This is used by plugins to bypass RLS filtering when fetching existing rows\n * for mutation validation. The table name comes from repository configuration\n * and is validated during repository creation.\n *\n * @param db - Kysely database instance\n * @param table - Table name (from repository config)\n * @returns Query builder for the table\n */\nexport function selectFromDynamicTable<DB>(\n db: Kysely<DB>,\n table: string\n): SelectQueryBuilder<Record<string, unknown>, string, Record<string, unknown>> {\n return db.selectFrom(table as any).selectAll() as any\n}\n\n/**\n * Add WHERE clause for primary key equality.\n * Supports custom primary key column names.\n *\n * @param qb - Select query builder\n * @param id - Primary key value\n * @param primaryKeyColumn - Primary key column name (default: 'id')\n * @returns Query builder with ID filter\n */\nexport function whereIdEquals(\n qb: SelectQueryBuilder<any, any, any>,\n id: unknown,\n primaryKeyColumn = 'id'\n): SelectQueryBuilder<any, any, any> {\n return qb.where(primaryKeyColumn as any, '=', id as any)\n}\n\n/**\n * Type-safe wrapper for transforming query builders in plugin interceptors\n *\n * Used when plugins need to transform a generic query builder (QB) to a specific\n * type (e.g., SelectQueryBuilder) and back. This is necessary because the executor's\n * interceptQuery hook receives unconstrained QB types to preserve type inference.\n *\n * @param qb - Generic query builder from interceptor\n * @param operation - Operation type (for runtime validation)\n * @param transform - Transformation function\n * @returns Transformed query builder\n */\nexport function transformQueryBuilder<QB>(\n qb: QB,\n operation: string,\n transform: (\n qb: SelectQueryBuilder<Record<string, unknown>, string, Record<string, unknown>>\n ) => SelectQueryBuilder<Record<string, unknown>, string, Record<string, unknown>>\n): QB {\n if (operation !== 'select') {\n return qb\n }\n\n const transformed = transform(qb as any)\n return transformed as QB\n}\n\n/**\n * Type guard to check if an executor has a raw db instance\n *\n * @param executor - Kysely executor (may have __rawDb property)\n * @returns True if executor has __rawDb property\n */\nexport function hasRawDb<DB>(\n executor: Kysely<DB>\n): executor is Kysely<DB> & { __rawDb: Kysely<DB> } {\n return '__rawDb' in executor && (executor as any).__rawDb !== undefined\n}\n\n/**\n * Type-safe wrapper to get raw db from executor\n *\n * @param executor - Kysely executor with optional __rawDb\n * @returns Raw db instance or original executor\n */\nexport function getRawDbSafe<DB>(executor: Kysely<DB>): Kysely<DB> {\n if (hasRawDb(executor)) {\n return executor.__rawDb\n }\n return executor\n}\n","/**\n * SELECT Query Transformer\n * Applies filter policies to SELECT queries by adding WHERE conditions\n */\n\nimport type { SelectQueryBuilder } from 'kysely'\nimport type { PolicyRegistry } from '../policy/registry.js'\nimport type { PolicyEvaluationContext } from '../policy/types.js'\nimport type { RLSContext } from '../context/types.js'\nimport { rlsContext } from '../context/manager.js'\nimport { RLSError, RLSErrorCodes } from '../errors.js'\nimport {\n createQualifiedColumn,\n applyWhereCondition,\n createRawCondition\n} from '../utils/type-utils.js'\n\n/**\n * SELECT query transformer\n * Applies filter policies to SELECT queries by adding WHERE conditions\n */\nexport class SelectTransformer<DB = unknown> {\n constructor(private registry: PolicyRegistry<DB>) {}\n\n /**\n * Transform a SELECT query by applying filter policies\n *\n * @param qb - The query builder to transform\n * @param table - Table name being queried\n * @returns Transformed query builder with RLS filters applied\n *\n * @example\n * ```typescript\n * const transformer = new SelectTransformer(registry);\n * let query = db.selectFrom('posts').selectAll();\n * query = transformer.transform(query, 'posts');\n * // Query now includes WHERE conditions from RLS policies\n * ```\n */\n transform<TB extends keyof DB & string, O>(\n qb: SelectQueryBuilder<DB, TB, O>,\n table: string\n ): SelectQueryBuilder<DB, TB, O> {\n // Check for context\n const ctx = rlsContext.getContextOrNull()\n if (!ctx) {\n // SECURITY FIX (H-11): This should never happen as plugin.interceptQuery\n // now handles missing context. If we reach here, apply defensive WHERE FALSE\n // to prevent unfiltered queries from leaking through.\n // This is a defense-in-depth measure.\n return applyWhereCondition(\n qb,\n createRawCondition('FALSE') as unknown as string,\n '=',\n true\n ) as SelectQueryBuilder<DB, TB, O>\n }\n\n // Check if system user (bypass RLS)\n if (ctx.auth.isSystem) {\n return qb\n }\n\n // Check if user role should skip RLS\n const skipFor = this.registry.getSkipFor(table)\n if (skipFor.some(role => ctx.auth.roles.includes(role))) {\n return qb\n }\n\n // Get filter policies for this table\n const filters = this.registry.getFilters(table)\n if (filters.length === 0) {\n return qb\n }\n\n // Apply each filter as WHERE condition\n let result = qb\n for (const filter of filters) {\n const conditions = this.evaluateFilter(filter, ctx, table)\n result = this.applyConditions(result, conditions, table)\n }\n\n return result\n }\n\n /**\n * Evaluate a filter policy to get WHERE conditions\n *\n * @param filter - The filter policy to evaluate\n * @param ctx - RLS context\n * @param table - Table name\n * @returns WHERE clause conditions as key-value pairs\n */\n private evaluateFilter(\n filter: {\n name: string\n getConditions: (\n ctx: PolicyEvaluationContext\n ) => Record<string, unknown> | Promise<Record<string, unknown>>\n },\n ctx: RLSContext,\n table: string\n ): Record<string, unknown> {\n const evalCtx: PolicyEvaluationContext = {\n auth: ctx.auth,\n ...(ctx.meta !== undefined && { meta: ctx.meta as Record<string, unknown> })\n }\n\n const result = filter.getConditions(evalCtx)\n\n // Note: If async filters are needed, this method signature would need to change\n // For now, we assume synchronous filter evaluation\n if (result instanceof Promise) {\n throw new RLSError(\n `Async filter policies are not supported in SELECT transformers. ` +\n `Filter '${filter.name}' on table '${table}' returned a Promise. ` +\n `Use synchronous conditions for filter policies.`,\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n return result\n }\n\n /**\n * Apply filter conditions to query builder\n *\n * Uses type-safe wrappers from utils/type-utils.ts to encapsulate the boundary\n * between runtime policy conditions and Kysely's compile-time type system.\n *\n * Type safety is maintained through:\n * 1. Policy conditions are validated during schema registration\n * 2. Column names come from policy definitions (developer-controlled)\n * 3. Values are type-checked by the policy condition functions\n *\n * @param qb - Query builder to modify\n * @param conditions - WHERE clause conditions\n * @param table - Table name (for qualified column names)\n * @returns Modified query builder\n */\n private applyConditions<TB extends keyof DB & string, O>(\n qb: SelectQueryBuilder<DB, TB, O>,\n conditions: Record<string, unknown>,\n table: string\n ): SelectQueryBuilder<DB, TB, O> {\n let result = qb\n\n for (const [column, value] of Object.entries(conditions)) {\n // Use table-qualified column name to avoid ambiguity in joins\n const qualifiedColumn = createQualifiedColumn(table, column)\n\n if (value === null) {\n // NULL check\n result = applyWhereCondition(result, qualifiedColumn, 'is', null)\n } else if (value === undefined) {\n // Skip undefined values\n continue\n } else if (Array.isArray(value)) {\n if (value.length === 0) {\n // Empty array means no matches - add impossible condition using SQL FALSE\n // This ensures the query returns no rows without using magic strings\n // that could potentially match actual data\n result = applyWhereCondition(\n result,\n createRawCondition('FALSE') as unknown as string,\n '=',\n true\n )\n } else {\n // IN clause for array values\n result = applyWhereCondition(result, qualifiedColumn, 'in', value)\n }\n } else {\n // Equality check\n result = applyWhereCondition(result, qualifiedColumn, '=', value)\n }\n }\n\n return result\n }\n}\n","/**\n * Mutation Guard\n * Validates CREATE, UPDATE, DELETE operations against RLS policies\n */\n\nimport type { PolicyRegistry } from '../policy/registry.js'\nimport type { PolicyEvaluationContext, Operation } from '../policy/types.js'\nimport type { RLSContext } from '../context/types.js'\nimport { rlsContext } from '../context/manager.js'\nimport { RLSPolicyViolation, RLSPolicyEvaluationError } from '../errors.js'\n\n/**\n * Default chunk size for parallel row filtering\n */\nconst DEFAULT_CHUNK_SIZE = 100\n\n/**\n * Mutation guard\n * Validates mutations (CREATE, UPDATE, DELETE) against allow/deny/validate policies\n */\nexport class MutationGuard<DB = unknown> {\n constructor(private registry: PolicyRegistry<DB>) {}\n\n /**\n * Check if CREATE operation is allowed\n *\n * @param table - Table name\n * @param data - Data being inserted\n * @throws RLSPolicyViolation if access is denied\n *\n * @example\n * ```typescript\n * const guard = new MutationGuard(registry);\n * await guard.checkCreate('posts', { title: 'Hello', tenant_id: 1 });\n * ```\n */\n async checkCreate(table: string, data: Record<string, unknown>): Promise<void> {\n await this.checkMutation(table, 'create', undefined, data)\n }\n\n /**\n * Check if UPDATE operation is allowed\n *\n * @param table - Table name\n * @param existingRow - Current row data\n * @param data - Data being updated\n * @throws RLSPolicyViolation if access is denied\n *\n * @example\n * ```typescript\n * const guard = new MutationGuard(registry);\n * const existingPost = await db.selectFrom('posts').where('id', '=', 1).selectAll().executeTakeFirst();\n * await guard.checkUpdate('posts', existingPost, { title: 'Updated' });\n * ```\n */\n async checkUpdate(\n table: string,\n existingRow: Record<string, unknown>,\n data: Record<string, unknown>\n ): Promise<void> {\n await this.checkMutation(table, 'update', existingRow, data)\n }\n\n /**\n * Check if DELETE operation is allowed\n *\n * @param table - Table name\n * @param existingRow - Row to be deleted\n * @throws RLSPolicyViolation if access is denied\n *\n * @example\n * ```typescript\n * const guard = new MutationGuard(registry);\n * const existingPost = await db.selectFrom('posts').where('id', '=', 1).selectAll().executeTakeFirst();\n * await guard.checkDelete('posts', existingPost);\n * ```\n */\n async checkDelete(table: string, existingRow: Record<string, unknown>): Promise<void> {\n await this.checkMutation(table, 'delete', existingRow)\n }\n\n /**\n * Check if READ operation is allowed on a specific row\n *\n * @param table - Table name\n * @param row - Row to check access for\n * @returns true if access is allowed\n *\n * @example\n * ```typescript\n * const guard = new MutationGuard(registry);\n * const post = await db.selectFrom('posts').where('id', '=', 1).selectAll().executeTakeFirst();\n * const canRead = await guard.checkRead('posts', post);\n * ```\n */\n async checkRead(table: string, row: Record<string, unknown>): Promise<boolean> {\n try {\n await this.checkMutation(table, 'read', row)\n return true\n } catch (error) {\n // Both policy violations and evaluation errors result in denial\n if (error instanceof RLSPolicyViolation || error instanceof RLSPolicyEvaluationError) {\n return false\n }\n throw error\n }\n }\n\n /**\n * Generic check for any operation (helper for testing)\n *\n * @param operation - Operation type\n * @param table - Table name\n * @param row - Existing row (for UPDATE/DELETE/READ)\n * @param data - New data (for CREATE/UPDATE)\n * @returns true if access is allowed, false otherwise\n */\n async canMutate(\n operation: Operation,\n table: string,\n row?: Record<string, unknown>,\n data?: Record<string, unknown>\n ): Promise<boolean> {\n try {\n await this.checkMutation(table, operation, row, data)\n return true\n } catch (error) {\n // Both policy violations and evaluation errors result in denial\n if (error instanceof RLSPolicyViolation || error instanceof RLSPolicyEvaluationError) {\n return false\n }\n throw error\n }\n }\n\n /**\n * Validate mutation data (for validate policies)\n *\n * @param operation - Operation type\n * @param table - Table name\n * @param data - New data (for CREATE/UPDATE)\n * @param row - Existing row (for UPDATE)\n * @returns true if valid, false otherwise\n */\n async validateMutation(\n operation: Operation,\n table: string,\n data: Record<string, unknown>,\n row?: Record<string, unknown>\n ): Promise<boolean> {\n const ctx = rlsContext.getContextOrNull()\n if (!ctx) {\n return false\n }\n\n // System users bypass validation\n if (ctx.auth.isSystem) {\n return true\n }\n\n // Check skipFor roles\n const skipFor = this.registry.getSkipFor(table)\n if (skipFor.some(role => ctx.auth.roles.includes(role))) {\n return true\n }\n\n // Get validate policies for this operation\n const validates = this.registry.getValidates(table, operation)\n if (validates.length === 0) {\n return true\n }\n\n // Build evaluation context\n const evalCtx: PolicyEvaluationContext = {\n auth: ctx.auth,\n row: row,\n data: data,\n table: table,\n operation: operation,\n ...(ctx.meta !== undefined && { meta: ctx.meta as Record<string, unknown> })\n }\n\n // All validate policies must pass\n for (const validate of validates) {\n const result = await this.evaluatePolicy(validate.evaluate, evalCtx, validate.name)\n if (!result) {\n return false\n }\n }\n\n return true\n }\n\n /**\n * Check mutation against RLS policies\n *\n * @param table - Table name\n * @param operation - Operation type\n * @param row - Existing row (for UPDATE/DELETE/READ)\n * @param data - New data (for CREATE/UPDATE)\n * @throws RLSPolicyViolation if access is denied\n */\n private async checkMutation(\n table: string,\n operation: Operation,\n row?: Record<string, unknown>,\n data?: Record<string, unknown>\n ): Promise<void> {\n const ctx = rlsContext.getContextOrNull()\n if (!ctx) {\n throw new RLSPolicyViolation(operation, table, 'No RLS context available')\n }\n\n // System users bypass all checks\n if (ctx.auth.isSystem) {\n return\n }\n\n // Check if user role should skip RLS\n const skipFor = this.registry.getSkipFor(table)\n if (skipFor.some(role => ctx.auth.roles.includes(role))) {\n return\n }\n\n // Evaluate deny policies first (they override allows)\n const denies = this.registry.getDenies(table, operation)\n for (const deny of denies) {\n const evalCtx = this.createEvalContext(ctx, table, operation, row, data)\n const result = await this.evaluatePolicy(deny.evaluate, evalCtx, deny.name)\n\n if (result) {\n throw new RLSPolicyViolation(operation, table, `Denied by policy: ${deny.name}`)\n }\n }\n\n // Evaluate validate policies (for CREATE/UPDATE)\n if ((operation === 'create' || operation === 'update') && data) {\n const validates = this.registry.getValidates(table, operation)\n for (const validate of validates) {\n const evalCtx = this.createEvalContext(ctx, table, operation, row, data)\n const result = await this.evaluatePolicy(validate.evaluate, evalCtx, validate.name)\n\n if (!result) {\n throw new RLSPolicyViolation(operation, table, `Validation failed: ${validate.name}`)\n }\n }\n }\n\n // Evaluate allow policies\n const allows = this.registry.getAllows(table, operation)\n const defaultDeny = this.registry.hasDefaultDeny(table)\n\n if (defaultDeny && allows.length === 0) {\n throw new RLSPolicyViolation(operation, table, 'No allow policies defined (default deny)')\n }\n\n if (allows.length > 0) {\n // At least one allow policy must pass\n let allowed = false\n\n for (const allow of allows) {\n const evalCtx = this.createEvalContext(ctx, table, operation, row, data)\n const result = await this.evaluatePolicy(allow.evaluate, evalCtx, allow.name)\n\n if (result) {\n allowed = true\n break\n }\n }\n\n if (!allowed) {\n throw new RLSPolicyViolation(operation, table, 'No allow policies matched')\n }\n }\n }\n\n /**\n * Create policy evaluation context\n */\n private createEvalContext(\n ctx: RLSContext,\n table: string,\n operation: Operation,\n row?: Record<string, unknown>,\n data?: Record<string, unknown>\n ): PolicyEvaluationContext {\n return {\n auth: ctx.auth,\n row,\n data,\n table,\n operation,\n ...(ctx.meta !== undefined && { meta: ctx.meta as Record<string, unknown> })\n }\n }\n\n /**\n * Evaluate a policy condition\n *\n * @param condition - Policy condition function\n * @param evalCtx - Policy evaluation context\n * @param policyName - Name of the policy being evaluated (for error reporting)\n * @returns Boolean result of policy evaluation\n * @throws RLSPolicyEvaluationError if the policy throws an error\n */\n private async evaluatePolicy(\n condition: (ctx: PolicyEvaluationContext) => boolean | Promise<boolean>,\n evalCtx: PolicyEvaluationContext,\n policyName?: string\n ): Promise<boolean> {\n try {\n const result = condition(evalCtx)\n return result instanceof Promise ? await result : result\n } catch (error) {\n // Distinguish between policy evaluation errors and policy violations\n // RLSPolicyEvaluationError indicates a bug in the policy, not a legitimate denial\n const originalError = error instanceof Error ? error : undefined\n throw new RLSPolicyEvaluationError(\n evalCtx.operation ?? 'unknown',\n evalCtx.table ?? 'unknown',\n error instanceof Error ? error.message : 'Unknown error',\n policyName,\n originalError\n )\n }\n }\n\n /**\n * Filter rows based on read policies.\n * Uses parallel processing with chunking for performance.\n *\n * @param table - Table name\n * @param rows - Rows to filter\n * @param chunkSize - Number of rows to process in parallel (default: 100)\n * @returns Filtered array containing only accessible rows\n *\n * @example\n * ```typescript\n * const guard = new MutationGuard(registry);\n * const allPosts = await db.selectFrom('posts').selectAll().execute();\n * const accessiblePosts = await guard.filterRows('posts', allPosts);\n *\n * // With custom chunk size for large datasets\n * const accessiblePosts = await guard.filterRows('posts', allPosts, 50);\n * ```\n */\n async filterRows<T extends Record<string, unknown>>(\n table: string,\n rows: T[],\n chunkSize: number = DEFAULT_CHUNK_SIZE\n ): Promise<T[]> {\n if (rows.length === 0) return []\n\n const results: T[] = []\n\n // Process in chunks to avoid overwhelming the event loop\n for (let i = 0; i < rows.length; i += chunkSize) {\n const chunk = rows.slice(i, i + chunkSize)\n\n // Process chunk in parallel\n const chunkResults = await Promise.all(\n chunk.map(async (row) => {\n const allowed = await this.checkRead(table, row)\n return allowed ? row : null\n })\n )\n\n // Filter out nulls and add to results\n for (const row of chunkResults) {\n if (row !== null) {\n results.push(row)\n }\n }\n }\n\n return results\n }\n}\n","/**\n * Package version - injected at build time by tsup\n * Falls back to development version if not replaced\n * @internal\n */\nconst RAW_VERSION = '__VERSION__'\nexport const VERSION = RAW_VERSION.startsWith('__') ? '0.0.0-dev' : RAW_VERSION\n","/**\n * RLS Plugin for Kysera Repository\n *\n * Implements Row-Level Security as a Kysera plugin, providing:\n * - Automatic query filtering for SELECT operations\n * - Policy enforcement for CREATE, UPDATE, DELETE operations\n * - Repository method extensions for RLS-aware operations\n * - System context bypass for privileged operations\n *\n * @module @kysera/rls\n */\n\nimport type { Plugin, QueryBuilderContext, BaseRepositoryLike } from '@kysera/executor'\nimport { getRawDb, isRepositoryLike } from '@kysera/executor'\nimport type { Kysely } from 'kysely'\nimport { z } from 'zod'\nimport type { RLSSchema, Operation } from './policy/types.js'\nimport { PolicyRegistry } from './policy/registry.js'\nimport { SelectTransformer } from './transformer/select.js'\nimport { MutationGuard } from './transformer/mutation.js'\nimport { rlsContext } from './context/manager.js'\nimport { VERSION } from './version.js'\nimport { RLSContextError, RLSPolicyViolation, RLSError, RLSErrorCodes } from './errors.js'\nimport { silentLogger, type KyseraLogger } from '@kysera/core'\nimport {\n transformQueryBuilder,\n selectFromDynamicTable,\n whereIdEquals,\n hasRawDb as hasRawDbUtil,\n applyWhereCondition,\n createRawCondition\n} from './utils/type-utils.js'\n\n/**\n * RLS Plugin configuration options\n */\nexport interface RLSPluginOptions<DB = unknown> {\n /** RLS policy schema */\n schema: RLSSchema<DB>\n\n /**\n * Tables to exclude from RLS (always bypass policies)\n * Replaces the deprecated `skipTables` option for consistency with other plugins.\n * @default []\n */\n excludeTables?: string[]\n\n /**\n * @deprecated Use `excludeTables` instead for consistency with other Kysera plugins\n * @default []\n */\n skipTables?: string[]\n\n /** Roles that bypass RLS entirely (e.g., ['admin', 'superuser']) */\n bypassRoles?: string[]\n\n /** Logger instance for RLS operations */\n logger?: KyseraLogger\n\n /**\n * Require RLS context for all operations (throws if missing)\n *\n * **Security**: Defaults to `true` for secure-by-default behavior.\n * When `true`, missing RLS context throws RLSContextError, preventing\n * unfiltered database access which could expose sensitive data.\n *\n * Only set to `false` if you explicitly want to allow queries without\n * RLS context (not recommended in production).\n *\n * @default true\n * @see allowUnfilteredQueries for explicit unfiltered query control\n */\n requireContext?: boolean\n\n /**\n * Allow unfiltered queries when RLS context is missing\n *\n * **SECURITY WARNING**: Setting this to `true` allows database queries\n * to execute without RLS filtering when context is missing. This can\n * expose sensitive data across tenant boundaries or user permissions.\n *\n * Only enable this if you:\n * 1. Understand the security implications\n * 2. Have other security controls in place\n * 3. Are running background jobs or system operations that don't have user context\n *\n * When both `requireContext: false` and `allowUnfilteredQueries: false`:\n * - Missing context logs a warning and returns empty results\n *\n * @default false (secure-by-default)\n */\n allowUnfilteredQueries?: boolean\n\n /** Enable audit logging of policy decisions */\n auditDecisions?: boolean\n\n /** Custom error handler for policy violations */\n onViolation?: (violation: RLSPolicyViolation) => void\n\n /**\n * Primary key column name for row lookups.\n * @default 'id'\n */\n primaryKeyColumn?: string\n}\n\n/**\n * Zod schema for RLSPluginOptions\n * Used for validation and configuration in the kysera-cli.\n * Note: 'schema' and 'onViolation' are not included as they are complex runtime objects.\n */\nexport const RLSPluginOptionsSchema = z.object({\n excludeTables: z.array(z.string()).optional(),\n skipTables: z.array(z.string()).optional(), // deprecated but kept for backward compatibility\n bypassRoles: z.array(z.string()).optional(),\n requireContext: z.boolean().optional(),\n allowUnfilteredQueries: z.boolean().optional(),\n auditDecisions: z.boolean().optional(),\n primaryKeyColumn: z.string().optional()\n})\n\n/**\n * Base repository interface for type safety.\n * Type alias for BaseRepositoryLike from @kysera/executor with concrete DB type.\n * @internal\n */\ntype BaseRepository = BaseRepositoryLike<Record<string, unknown>>\n\n/**\n * Create RLS plugin for Kysera\n *\n * The RLS plugin provides declarative row-level security for your database operations.\n * It automatically filters SELECT queries and validates mutations (CREATE, UPDATE, DELETE)\n * against your policy schema.\n *\n * @example\n * ```typescript\n * import { rlsPlugin, defineRLSSchema, allow, filter } from '@kysera/rls';\n * import { createORM } from '@kysera/repository';\n *\n * // Define your RLS schema\n * const schema = defineRLSSchema<Database>({\n * resources: {\n * policies: [\n * // Filter reads by tenant\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId })),\n * // Allow updates for resource owners\n * allow('update', ctx => ctx.auth.userId === ctx.row.owner_id),\n * // Validate creates belong to user's tenant\n * validate('create', ctx => ctx.data.tenant_id === ctx.auth.tenantId),\n * ],\n * },\n * });\n *\n * // Create repository with RLS plugin\n * const orm = await createORM(db, [\n * rlsPlugin({ schema }),\n * ]);\n *\n * // Use within RLS context\n * await rlsContext.runAsync(\n * {\n * auth: { userId: 1, tenantId: 100, roles: ['user'], isSystem: false },\n * timestamp: new Date(),\n * },\n * async () => {\n * // All queries automatically filtered by tenant_id\n * const resources = await orm.resources.findAll();\n * }\n * );\n * ```\n *\n * @param options - Plugin configuration options\n * @returns Kysera plugin instance\n */\nexport function rlsPlugin<DB>(options: RLSPluginOptions<DB>): Plugin {\n const {\n schema,\n excludeTables: excludeTablesOption,\n skipTables: skipTablesOption,\n bypassRoles = [],\n logger = silentLogger,\n requireContext = true, // SECURITY: Changed to true for secure-by-default (CRIT-2 fix)\n allowUnfilteredQueries = false, // SECURITY: Explicit opt-in for unfiltered queries\n auditDecisions = false,\n onViolation,\n primaryKeyColumn = 'id'\n } = options\n\n // Backward compatibility: support both excludeTables and skipTables\n // excludeTables takes precedence if both are provided\n const excludeTables = excludeTablesOption ?? skipTablesOption ?? []\n\n // Warn if deprecated skipTables is used\n if (skipTablesOption !== undefined && excludeTablesOption === undefined) {\n logger.warn?.(\n '[RLS] The \"skipTables\" option is deprecated. Use \"excludeTables\" instead for consistency with other Kysera plugins.'\n )\n }\n\n // Registry and transformers (initialized in onInit)\n let registry: PolicyRegistry<DB>\n let selectTransformer: SelectTransformer<DB>\n let mutationGuard: MutationGuard<DB>\n\n return {\n name: '@kysera/rls',\n version: VERSION,\n\n // Run after soft-delete (priority 0), before audit\n priority: 50,\n\n // No dependencies by default\n dependencies: [],\n\n /**\n * Initialize plugin - compile policies\n */\n onInit<TDB>(_executor: Kysely<TDB>): void {\n logger.info?.('[RLS] Initializing RLS plugin', {\n tables: Object.keys(schema).length,\n excludeTables: excludeTables.length,\n bypassRoles: bypassRoles.length\n })\n\n // Create and compile registry\n // Type assertion: The plugin is configured with a specific DB schema,\n // but onInit receives a generic TDB. We use the schema's DB type.\n registry = new PolicyRegistry<DB>(schema)\n registry.validate()\n\n // Create transformers\n selectTransformer = new SelectTransformer<DB>(registry)\n mutationGuard = new MutationGuard<DB>(registry)\n\n logger.info?.('[RLS] RLS plugin initialized successfully')\n },\n\n /**\n * Cleanup resources when executor is destroyed\n */\n async onDestroy(): Promise<void> {\n // Clear registry to free up memory\n registry.clear()\n logger.info?.('[RLS] RLS plugin destroyed, cleared policy registry')\n },\n\n /**\n * Intercept queries to apply RLS filtering\n *\n * This hook is called for every query builder operation. For SELECT queries,\n * it applies filter policies as WHERE conditions. For mutations, it marks\n * that RLS validation is required (performed in extendRepository).\n */\n interceptQuery<QB>(qb: QB, context: QueryBuilderContext): QB {\n const { operation, table, metadata } = context\n\n // Skip if table is excluded\n if (excludeTables.includes(table)) {\n logger.debug?.(`[RLS] Skipping RLS for excluded table: ${table}`)\n return qb\n }\n\n // Skip if explicitly disabled via metadata\n if (metadata['skipRLS'] === true) {\n logger.debug?.(`[RLS] Skipping RLS (explicit skip): ${table}`)\n return qb\n }\n\n // Check for context\n const ctx = rlsContext.getContextOrNull()\n\n if (!ctx) {\n // SECURITY FIX (CRIT-2): Secure-by-default behavior for missing context\n if (requireContext) {\n throw new RLSContextError(\n `RLS context required but not found for ${operation} on ${table}. ` +\n `This prevents unfiltered database access. ` +\n `Either provide RLS context or set 'requireContext: false' with 'allowUnfilteredQueries: true' if intentional.`\n )\n }\n\n if (!allowUnfilteredQueries) {\n // Log warning and return safe empty result\n logger.warn?.(\n `[RLS] Missing context for ${operation} on ${table}. ` +\n `Queries will return empty results for security. ` +\n `Set 'allowUnfilteredQueries: true' to allow unfiltered access (not recommended).`\n )\n // For SELECT, apply impossible condition to return no rows\n if (operation === 'select') {\n return transformQueryBuilder(qb, operation, selectQb => {\n // Apply WHERE FALSE to ensure no rows are returned\n return applyWhereCondition(\n selectQb,\n createRawCondition('FALSE') as unknown as string,\n '=',\n true\n ) as typeof selectQb\n })\n }\n // For mutations, we'll let them through but log warning\n // The extendRepository will handle mutation checks\n return qb\n }\n\n // allowUnfilteredQueries is true - allow but log warning\n logger.warn?.(\n `[RLS] No context for ${operation} on ${table}. ` +\n `Allowing unfiltered query due to 'allowUnfilteredQueries: true'. ` +\n `This may expose sensitive data.`\n )\n return qb\n }\n\n // Check if system user (bypass RLS)\n if (ctx.auth.isSystem) {\n logger.debug?.(`[RLS] Bypassing RLS (system user): ${table}`)\n return qb\n }\n\n // Check bypass roles\n if (bypassRoles.some(role => ctx.auth.roles.includes(role))) {\n logger.debug?.(`[RLS] Bypassing RLS (bypass role): ${table}`)\n return qb\n }\n\n // Apply SELECT filtering\n if (operation === 'select') {\n try {\n const transformed = transformQueryBuilder(\n qb,\n operation,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n selectQb => selectTransformer.transform(selectQb as any, table) as any\n )\n\n if (auditDecisions) {\n logger.info?.('[RLS] Filter applied', {\n table,\n operation,\n userId: ctx.auth.userId\n })\n }\n\n return transformed\n } catch (error) {\n logger.error?.('[RLS] Error applying filter', { table, error })\n throw error\n }\n }\n\n // For mutations, mark that RLS check is needed (done in extendRepository)\n if (operation === 'insert' || operation === 'update' || operation === 'delete') {\n metadata['__rlsRequired'] = true\n metadata['__rlsTable'] = table\n }\n\n return qb\n },\n\n /**\n * Extend repository with RLS-aware methods\n *\n * Wraps create, update, and delete methods to enforce RLS policies.\n * Also adds utility methods for bypassing RLS and checking access.\n */\n extendRepository<T extends object>(repo: T): T {\n // Use the shared type guard from @kysera/executor\n if (!isRepositoryLike(repo)) {\n return repo\n }\n\n const baseRepo = repo as unknown as BaseRepository\n\n const table = baseRepo.tableName\n\n // Skip excluded tables\n if (excludeTables.includes(table)) {\n logger.debug?.(`[RLS] Skipping repository extension for excluded table: ${table}`)\n return repo\n }\n\n // Skip if table not in schema\n if (!registry.hasTable(table)) {\n logger.debug?.(`[RLS] Table \"${table}\" not in RLS schema, skipping`)\n return repo\n }\n\n logger.debug?.(`[RLS] Extending repository for table: ${table}`)\n\n // Store original methods\n const originalCreate = baseRepo.create?.bind(baseRepo)\n const originalUpdate = baseRepo.update?.bind(baseRepo)\n const originalDelete = baseRepo.delete?.bind(baseRepo)\n const originalFindById = baseRepo.findById?.bind(baseRepo)\n\n // Get raw db for internal queries that need to bypass RLS\n // If executor doesn't have __rawDb (e.g., in tests), we'll use originalFindById\n const rawDb = getRawDb(baseRepo.executor)\n const hasRawDbInstance = hasRawDbUtil(baseRepo.executor)\n\n const extendedRepo = {\n ...baseRepo,\n\n /**\n * Wrapped create with RLS check\n */\n async create(data: unknown): Promise<unknown> {\n if (!originalCreate) {\n throw new RLSError(\n 'Repository does not support create operation',\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n const ctx = rlsContext.getContextOrNull()\n\n // Check RLS if context exists and not system/bypass\n if (\n ctx &&\n !ctx.auth.isSystem &&\n !bypassRoles.some(role => ctx.auth.roles.includes(role))\n ) {\n try {\n await mutationGuard.checkCreate(table, data as Record<string, unknown>)\n\n if (auditDecisions) {\n logger.info?.('[RLS] Create allowed', { table, userId: ctx.auth.userId })\n }\n } catch (error) {\n if (error instanceof RLSPolicyViolation) {\n onViolation?.(error)\n if (auditDecisions) {\n logger.warn?.('[RLS] Create denied', {\n table,\n userId: ctx.auth.userId,\n reason: error.reason\n })\n }\n }\n throw error\n }\n }\n\n return await originalCreate(data)\n },\n\n /**\n * Wrapped update with RLS check\n */\n async update(id: unknown, data: unknown): Promise<unknown> {\n if (!originalUpdate) {\n throw new RLSError(\n 'Repository does not support update operation',\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n const ctx = rlsContext.getContextOrNull()\n\n if (\n ctx &&\n !ctx.auth.isSystem &&\n !bypassRoles.some(role => ctx.auth.roles.includes(role))\n ) {\n // Fetch existing row for policy evaluation\n // Use raw db if available to bypass RLS filtering and prevent self-interception\n let existingRow: unknown\n\n if (hasRawDbInstance) {\n // Use raw db to bypass RLS filtering\n const query = selectFromDynamicTable(rawDb, table)\n existingRow = await whereIdEquals(query, id, primaryKeyColumn).executeTakeFirst()\n } else if (originalFindById) {\n // Fallback to originalFindById for tests/mocks\n existingRow = await originalFindById(id)\n } else {\n throw new RLSError(\n 'Repository does not support update operation',\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n if (!existingRow) {\n // Let the original method handle not found\n return await originalUpdate(id, data)\n }\n\n try {\n await mutationGuard.checkUpdate(\n table,\n existingRow as Record<string, unknown>,\n data as Record<string, unknown>\n )\n\n if (auditDecisions) {\n logger.info?.('[RLS] Update allowed', { table, id, userId: ctx.auth.userId })\n }\n } catch (error) {\n if (error instanceof RLSPolicyViolation) {\n onViolation?.(error)\n if (auditDecisions) {\n logger.warn?.('[RLS] Update denied', {\n table,\n id,\n userId: ctx.auth.userId,\n reason: error.reason\n })\n }\n }\n throw error\n }\n }\n\n return await originalUpdate(id, data)\n },\n\n /**\n * Wrapped delete with RLS check\n */\n async delete(id: unknown): Promise<unknown> {\n if (!originalDelete) {\n throw new RLSError(\n 'Repository does not support delete operation',\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n const ctx = rlsContext.getContextOrNull()\n\n if (\n ctx &&\n !ctx.auth.isSystem &&\n !bypassRoles.some(role => ctx.auth.roles.includes(role))\n ) {\n // Fetch existing row for policy evaluation\n // Use raw db if available to bypass RLS filtering and prevent self-interception\n let existingRow: unknown\n\n if (hasRawDbInstance) {\n // Use raw db to bypass RLS filtering\n const query = selectFromDynamicTable(rawDb, table)\n existingRow = await whereIdEquals(query, id, primaryKeyColumn).executeTakeFirst()\n } else if (originalFindById) {\n // Fallback to originalFindById for tests/mocks\n existingRow = await originalFindById(id)\n } else {\n throw new RLSError(\n 'Repository does not support delete operation',\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n if (!existingRow) {\n // Let the original method handle not found\n return await originalDelete(id)\n }\n\n try {\n await mutationGuard.checkDelete(table, existingRow as Record<string, unknown>)\n\n if (auditDecisions) {\n logger.info?.('[RLS] Delete allowed', { table, id, userId: ctx.auth.userId })\n }\n } catch (error) {\n if (error instanceof RLSPolicyViolation) {\n onViolation?.(error)\n if (auditDecisions) {\n logger.warn?.('[RLS] Delete denied', {\n table,\n id,\n userId: ctx.auth.userId,\n reason: error.reason\n })\n }\n }\n throw error\n }\n }\n\n return await originalDelete(id)\n },\n\n /**\n * Bypass RLS for specific operation\n * Requires existing context\n *\n * @example\n * ```typescript\n * // Perform operation as system user\n * const result = await repo.withoutRLS(async () => {\n * return repo.findAll(); // No RLS filtering\n * });\n * ```\n */\n async withoutRLS<R>(fn: () => Promise<R>): Promise<R> {\n return await rlsContext.asSystemAsync(fn)\n },\n\n /**\n * Check if current user can perform operation on a row\n *\n * @example\n * ```typescript\n * const post = await repo.findById(1);\n * const canUpdate = await repo.canAccess('update', post);\n * if (canUpdate) {\n * await repo.update(1, { title: 'New title' });\n * }\n * ```\n */\n async canAccess(operation: Operation, row: Record<string, unknown>): Promise<boolean> {\n const ctx = rlsContext.getContextOrNull()\n if (!ctx) return false\n if (ctx.auth.isSystem) return true\n if (bypassRoles.some(role => ctx.auth.roles.includes(role))) return true\n\n try {\n switch (operation) {\n case 'read':\n return await mutationGuard.checkRead(table, row)\n case 'create':\n await mutationGuard.checkCreate(table, row)\n return true\n case 'update':\n await mutationGuard.checkUpdate(table, row, {})\n return true\n case 'delete':\n await mutationGuard.checkDelete(table, row)\n return true\n default:\n return false\n }\n } catch (error) {\n logger.debug?.('[RLS] Access check failed', {\n table,\n operation,\n error: error instanceof Error ? error.message : String(error)\n })\n return false\n }\n }\n }\n\n return extendedRepo as T\n }\n }\n}\n","/**\n * Utility helper functions for RLS\n */\n\nimport type { RLSContext, PolicyEvaluationContext, Operation } from '../policy/types.js'\n\n/**\n * Create a policy evaluation context from RLS context\n */\nexport function createEvaluationContext<TRow = unknown, TData = unknown>(\n rlsCtx: RLSContext,\n options?: {\n row?: TRow\n data?: TData\n }\n): PolicyEvaluationContext<unknown, TRow, TData> {\n const ctx: PolicyEvaluationContext<unknown, TRow, TData> = {\n auth: rlsCtx.auth\n }\n\n if (options?.row !== undefined) {\n ctx.row = options.row\n }\n\n if (options?.data !== undefined) {\n ctx.data = options.data\n }\n\n if (rlsCtx.request !== undefined) {\n ctx.request = rlsCtx.request\n }\n\n if (rlsCtx.meta !== undefined) {\n ctx.meta = rlsCtx.meta as Record<string, unknown>\n }\n\n return ctx\n}\n\n/**\n * Check if a condition function is async\n *\n * NOTE: This function checks both constructor.name (for native async functions)\n * and return type (for transpiled code that returns Promise).\n * Transpilers often convert async functions to regular functions that return Promise.\n */\nexport function isAsyncFunction(fn: unknown): fn is (...args: unknown[]) => Promise<unknown> {\n if (!(fn instanceof Function)) {\n return false\n }\n\n // Check constructor name for native async functions\n if (fn.constructor.name === 'AsyncFunction') {\n return true\n }\n\n // For transpiled code: call the function with empty args and check if it returns a Promise\n // This is safe because policy conditions should be pure functions\n try {\n const result = (fn as Function)()\n return result instanceof Promise\n } catch {\n // If calling with no args throws, assume it's not async\n // (async functions that require args should be wrapped in the policy definition)\n return false\n }\n}\n\n/**\n * Safely evaluate a policy condition\n */\nexport async function safeEvaluate<T>(fn: () => T | Promise<T>, defaultValue: T): Promise<T> {\n try {\n const result = fn()\n if (result instanceof Promise) {\n return await result\n }\n return result\n } catch (_error) {\n // Expected failure during policy evaluation - return default value\n // Logger not available in this utility function, error is handled gracefully\n return defaultValue\n }\n}\n\n/**\n * Deep merge two objects\n */\nexport function deepMerge<T extends Record<string, unknown>>(target: T, source: Partial<T>): T {\n const result = { ...target }\n\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceValue = source[key]\n const targetValue = result[key]\n\n if (\n sourceValue !== undefined &&\n typeof sourceValue === 'object' &&\n sourceValue !== null &&\n !Array.isArray(sourceValue) &&\n typeof targetValue === 'object' &&\n targetValue !== null &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>\n ) as T[keyof T]\n } else if (sourceValue !== undefined) {\n result[key] = sourceValue as T[keyof T]\n }\n }\n\n return result\n}\n\n/**\n * Create a simple hash for cache keys\n */\nexport function hashString(str: string): string {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32bit integer\n }\n return hash.toString(36)\n}\n\n/**\n * Normalize operations to array format\n */\nexport function normalizeOperations(operation: Operation | Operation[]): Operation[] {\n if (Array.isArray(operation)) {\n if (operation.includes('all')) {\n return ['read', 'create', 'update', 'delete']\n }\n return operation\n }\n\n if (operation === 'all') {\n return ['read', 'create', 'update', 'delete']\n }\n\n return [operation]\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/policy/schema.ts","../src/policy/builder.ts","../src/policy/registry.ts","../src/context/storage.ts","../src/context/manager.ts","../src/utils/type-utils.ts","../src/transformer/select.ts","../src/transformer/mutation.ts","../src/version.ts","../src/plugin.ts","../src/utils/helpers.ts"],"names":["allow","deny","validate","filter","silentLogger"],"mappings":";;;;;;;AAuBO,IAAM,aAAA,GAAgB;AAAA;AAAA,EAE3B,mBAAA,EAAqB,qBAAA;AAAA;AAAA,EAErB,oBAAA,EAAsB,sBAAA;AAAA;AAAA,EAEtB,kBAAA,EAAoB,oBAAA;AAAA;AAAA,EAEpB,kBAAA,EAAoB,oBAAA;AAAA;AAAA,EAEpB,mBAAA,EAAqB,qBAAA;AAAA;AAAA,EAErB,2BAAA,EAA6B;AAC/B;AAsBO,IAAM,QAAA,GAAN,cAAuB,aAAA,CAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1C,WAAA,CAAY,SAAiB,IAAA,EAAoB;AAC/C,IAAA,KAAA,CAAM,SAAS,IAAI,CAAA;AACnB,IAAA,IAAA,CAAK,IAAA,GAAO,UAAA;AAAA,EACd;AACF;AAuBO,IAAM,eAAA,GAAN,cAA8B,QAAA,CAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM5C,WAAA,CAAY,UAAU,gEAAA,EAAkE;AACtF,IAAA,KAAA,CAAM,OAAA,EAAS,cAAc,mBAAmB,CAAA;AAChD,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAyBO,IAAM,yBAAA,GAAN,cAAwC,QAAA,CAAS;AAAA,EACtC,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQhB,WAAA,CAAY,SAAiB,KAAA,EAAe;AAC1C,IAAA,KAAA,CAAM,OAAA,EAAS,cAAc,mBAAmB,CAAA;AAChD,IAAA,IAAA,CAAK,IAAA,GAAO,2BAAA;AACZ,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACf;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO;AAAA,MACL,GAAG,MAAM,MAAA,EAAO;AAAA,MAChB,OAAO,IAAA,CAAK;AAAA,KACd;AAAA,EACF;AACF;AAwBO,IAAM,kBAAA,GAAN,cAAiC,QAAA,CAAS;AAAA,EAC/B,SAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUhB,WAAA,CAAY,SAAA,EAAmB,KAAA,EAAe,MAAA,EAAgB,UAAA,EAAqB;AACjF,IAAA,KAAA;AAAA,MACE,CAAA,sBAAA,EAAyB,SAAS,CAAA,IAAA,EAAO,KAAK,MAAM,MAAM,CAAA,CAAA;AAAA,MAC1D,aAAA,CAAc;AAAA,KAChB;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AACZ,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,MAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,IACpB;AAAA,EACF;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,MAAM,IAAA,GAAgC;AAAA,MACpC,GAAG,MAAM,MAAA,EAAO;AAAA,MAChB,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK;AAAA,KACf;AACA,IAAA,IAAI,IAAA,CAAK,eAAe,MAAA,EAAW;AACjC,MAAA,IAAA,CAAK,YAAY,IAAI,IAAA,CAAK,UAAA;AAAA,IAC5B;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAsBO,IAAM,wBAAA,GAAN,cAAuC,QAAA,CAAS;AAAA,EACrC,SAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,aAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWhB,WAAA,CACE,SAAA,EACA,KAAA,EACA,OAAA,EACA,YACA,aAAA,EACA;AACA,IAAA,KAAA;AAAA,MACE,CAAA,mCAAA,EAAsC,SAAS,CAAA,IAAA,EAAO,KAAK,KAAK,OAAO,CAAA,CAAA;AAAA,MACvE,aAAA,CAAc;AAAA,KAChB;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,0BAAA;AACZ,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,MAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,IACpB;AACA,IAAA,IAAI,kBAAkB,MAAA,EAAW;AAC/B,MAAA,IAAA,CAAK,aAAA,GAAgB,aAAA;AAErB,MAAA,IAAI,cAAc,KAAA,EAAO;AACvB,QAAA,IAAA,CAAK,KAAA,GAAQ,CAAA,EAAG,IAAA,CAAK,KAAK;;AAAA;AAAA,EAAmB,cAAc,KAAK,CAAA,CAAA;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,MAAM,IAAA,GAAgC;AAAA,MACpC,GAAG,MAAM,MAAA,EAAO;AAAA,MAChB,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,OAAO,IAAA,CAAK;AAAA,KACd;AACA,IAAA,IAAI,IAAA,CAAK,eAAe,MAAA,EAAW;AACjC,MAAA,IAAA,CAAK,YAAY,IAAI,IAAA,CAAK,UAAA;AAAA,IAC5B;AACA,IAAA,IAAI,IAAA,CAAK,kBAAkB,MAAA,EAAW;AACpC,MAAA,IAAA,CAAK,eAAe,CAAA,GAAI;AAAA,QACtB,IAAA,EAAM,KAAK,aAAA,CAAc,IAAA;AAAA,QACzB,OAAA,EAAS,KAAK,aAAA,CAAc;AAAA,OAC9B;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAiCO,IAAM,cAAA,GAAN,cAA6B,QAAA,CAAS;AAAA,EAC3B,OAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQhB,WAAA,CAAY,OAAA,EAAiB,OAAA,GAAmC,EAAC,EAAG;AAClE,IAAA,KAAA,CAAM,OAAA,EAAS,cAAc,kBAAkB,CAAA;AAC/C,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO;AAAA,MACL,GAAG,MAAM,MAAA,EAAO;AAAA,MAChB,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,EACF;AACF;;;AC9SO,SAAS,gBAAoB,MAAA,EAAsC;AAExE,EAAA,cAAA,CAAe,MAAM,CAAA;AACrB,EAAA,OAAO,MAAA;AACT;AAQA,SAAS,eAAmB,MAAA,EAA6B;AACvD,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,MAAM,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACpD,IAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,IAAA,MAAM,WAAA,GAAc,MAAA;AAEpB,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,WAAA,CAAY,QAAQ,CAAA,EAAG;AACxC,MAAA,MAAM,IAAI,cAAA,CAAe,CAAA,4BAAA,EAA+B,KAAK,CAAA,mBAAA,CAAA,EAAuB,EAAE,OAAO,CAAA;AAAA,IAC/F;AAGA,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,WAAA,CAAY,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACpD,MAAA,MAAM,MAAA,GAAS,WAAA,CAAY,QAAA,CAAS,CAAC,CAAA;AACrC,MAAA,IAAI,WAAW,MAAA,EAAW;AACxB,QAAA,cAAA,CAAe,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA,MACjC;AAAA,IACF;AAGA,IAAA,IAAI,WAAA,CAAY,YAAY,MAAA,EAAW;AACrC,MAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,WAAA,CAAY,OAAO,CAAA,EAAG;AACvC,QAAA,MAAM,IAAI,cAAA;AAAA,UACR,8BAA8B,KAAK,CAAA,iCAAA,CAAA;AAAA,UACnC,EAAE,KAAA;AAAM,SACV;AAAA,MACF;AAGA,MAAA,KAAA,MAAW,IAAA,IAAQ,YAAY,OAAA,EAAS;AACtC,QAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,IAAA,OAAW,EAAA,EAAI;AAClD,UAAA,MAAM,IAAI,cAAA;AAAA,YACR,sCAAsC,KAAK,CAAA,6BAAA,CAAA;AAAA,YAC3C,EAAE,KAAA;AAAM,WACV;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,YAAY,WAAA,KAAgB,MAAA,IAAa,OAAO,WAAA,CAAY,gBAAgB,SAAA,EAAW;AACzF,MAAA,MAAM,IAAI,cAAA,CAAe,CAAA,+BAAA,EAAkC,KAAK,CAAA,oBAAA,CAAA,EAAwB;AAAA,QACtF;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF;AACF;AAQA,SAAS,cAAA,CAAe,MAAA,EAA0B,KAAA,EAAe,KAAA,EAAqB;AACpF,EAAA,IAAI,CAAC,OAAO,IAAA,EAAM;AAChB,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,OAAA,EAAU,KAAK,CAAA,YAAA,EAAe,KAAK,CAAA,cAAA,CAAA,EAAkB,EAAE,KAAA,EAAO,KAAA,EAAO,CAAA;AAAA,EAChG;AAEA,EAAA,MAAM,UAAA,GAAa,CAAC,OAAA,EAAS,MAAA,EAAQ,UAAU,UAAU,CAAA;AACzD,EAAA,IAAI,CAAC,UAAA,CAAW,QAAA,CAAS,MAAA,CAAO,IAAI,CAAA,EAAG;AACrC,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,UAAU,KAAK,CAAA,YAAA,EAAe,KAAK,CAAA,oBAAA,EAAuB,OAAO,IAAI,CAAA,CAAA;AAAA,MACrE,EAAE,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,OAAO,IAAA;AAAK,KACpC;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,OAAO,SAAA,EAAW;AACrB,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,OAAA,EAAU,KAAK,CAAA,YAAA,EAAe,KAAK,CAAA,mBAAA,CAAA,EAAuB;AAAA,MACjF,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,WAAW,CAAC,MAAA,EAAQ,QAAA,EAAU,QAAA,EAAU,UAAU,KAAK,CAAA;AAC7D,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,SAAS,IAAI,MAAA,CAAO,SAAA,GAAY,CAAC,MAAA,CAAO,SAAS,CAAA;AAElF,EAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,IAAA,IAAI,CAAC,QAAA,CAAS,QAAA,CAAS,EAAE,CAAA,EAAG;AAC1B,MAAA,MAAM,IAAI,cAAA;AAAA,QACR,CAAA,OAAA,EAAU,KAAK,CAAA,YAAA,EAAe,KAAK,4BAA4B,EAAE,CAAA,CAAA;AAAA,QACjE,EAAE,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,EAAA;AAAG,OAChC;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,SAAA,KAAc,MAAA,IAAa,MAAA,CAAO,cAAc,IAAA,EAAM;AAC/D,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,OAAA,EAAU,KAAK,CAAA,YAAA,EAAe,KAAK,CAAA,mBAAA,CAAA,EAAuB;AAAA,MACjF,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AAEA,EAAA,IAAI,OAAO,MAAA,CAAO,SAAA,KAAc,cAAc,OAAO,MAAA,CAAO,cAAc,QAAA,EAAU;AAClF,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,OAAA,EAAU,KAAK,CAAA,YAAA,EAAe,KAAK,CAAA,wCAAA,CAAA;AAAA,MACnC,EAAE,OAAO,KAAA;AAAM,KACjB;AAAA,EACF;AAGA,EAAA,IAAI,OAAO,QAAA,KAAa,MAAA,IAAa,OAAO,MAAA,CAAO,aAAa,QAAA,EAAU;AACxE,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,OAAA,EAAU,KAAK,CAAA,YAAA,EAAe,KAAK,CAAA,2BAAA,CAAA,EAA+B;AAAA,MACzF,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AAGA,EAAA,IAAI,OAAO,IAAA,KAAS,MAAA,IAAa,OAAO,MAAA,CAAO,SAAS,QAAA,EAAU;AAChE,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,OAAA,EAAU,KAAK,CAAA,YAAA,EAAe,KAAK,CAAA,uBAAA,CAAA,EAA2B;AAAA,MACrF,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF;AA4BO,SAAS,mBAAuB,OAAA,EAAyC;AAC9E,EAAA,MAAM,SAAwB,EAAC;AAE/B,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,MAAM,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACpD,MAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,MAAA,MAAM,cAAA,GAAiB,OAAO,KAAiB,CAAA;AAC/C,MAAA,MAAM,SAAA,GAAY,MAAA;AAElB,MAAA,IAAI,cAAA,EAAgB;AAElB,QAAA,cAAA,CAAe,WAAW,CAAC,GAAG,eAAe,QAAA,EAAU,GAAG,UAAU,QAAQ,CAAA;AAG5E,QAAA,IAAI,UAAU,OAAA,EAAS;AACrB,UAAA,MAAM,eAAA,GAAkB,cAAA,CAAe,OAAA,IAAW,EAAC;AACnD,UAAA,MAAM,kBAAkB,CAAC,GAAG,eAAA,EAAiB,GAAG,UAAU,OAAO,CAAA;AACjE,UAAA,cAAA,CAAe,UAAU,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,eAAe,CAAC,CAAA;AAAA,QAC9D;AAGA,QAAA,IAAI,SAAA,CAAU,gBAAgB,MAAA,EAAW;AACvC,UAAA,cAAA,CAAe,cAAc,SAAA,CAAU,WAAA;AAAA,QACzC;AAAA,MACF,CAAA,MAAO;AAOL,QAAA,MAAA,CAAO,KAAiB,CAAA,GAAI;AAAA,UAC1B,QAAA,EAAU,CAAC,GAAG,SAAA,CAAU,QAAQ,CAAA;AAAA,UAChC,SAAS,SAAA,CAAU,OAAA,GAAU,CAAC,GAAG,SAAA,CAAU,OAAO,CAAA,GAAI,MAAA;AAAA,UACtD,aAAa,SAAA,CAAU;AAAA,SACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,cAAA,CAAe,MAAM,CAAA;AAErB,EAAA,OAAO,MAAA;AACT;;;AC/LO,SAAS,KAAA,CACd,SAAA,EACA,SAAA,EACA,OAAA,EACkB;AAClB,EAAA,MAAM,MAAA,GAA2B;AAAA,IAC/B,IAAA,EAAM,OAAA;AAAA,IACN,SAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA,EAAU,SAAS,QAAA,IAAY;AAAA,GACjC;AAEA,EAAA,IAAI,OAAA,EAAS,SAAS,MAAA,EAAW;AAC/B,IAAA,MAAA,CAAO,OAAO,OAAA,CAAQ,IAAA;AAAA,EACxB;AAEA,EAAA,IAAI,OAAA,EAAS,UAAU,MAAA,EAAW;AAChC,IAAA,MAAA,CAAO,QAAQ,OAAA,CAAQ,KAAA;AAAA,EACzB;AAEA,EAAA,OAAO,MAAA;AACT;AAyBO,SAAS,IAAA,CACd,SAAA,EACA,SAAA,EACA,OAAA,EACkB;AAClB,EAAA,MAAM,MAAA,GAA2B;AAAA,IAC/B,IAAA,EAAM,MAAA;AAAA,IACN,SAAA;AAAA,IACA,SAAA,EAAW,cAAc,MAAM,IAAA,CAAA;AAAA,IAC/B,QAAA,EAAU,SAAS,QAAA,IAAY;AAAA;AAAA,GACjC;AAEA,EAAA,IAAI,OAAA,EAAS,SAAS,MAAA,EAAW;AAC/B,IAAA,MAAA,CAAO,OAAO,OAAA,CAAQ,IAAA;AAAA,EACxB;AAEA,EAAA,IAAI,OAAA,EAAS,UAAU,MAAA,EAAW;AAChC,IAAA,MAAA,CAAO,QAAQ,OAAA,CAAQ,KAAA;AAAA,EACzB;AAEA,EAAA,OAAO,MAAA;AACT;AAsCO,SAAS,MAAA,CACd,SAAA,EACA,SAAA,EACA,OAAA,EACkB;AAClB,EAAA,MAAM,MAAA,GAA2B;AAAA,IAC/B,IAAA,EAAM,QAAA;AAAA,IACN,SAAA,EAAW,SAAA,KAAc,KAAA,GAAQ,MAAA,GAAS,SAAA;AAAA,IAC1C,SAAA;AAAA,IACA,QAAA,EAAU,SAAS,QAAA,IAAY;AAAA,GACjC;AAEA,EAAA,IAAI,OAAA,EAAS,SAAS,MAAA,EAAW;AAC/B,IAAA,MAAA,CAAO,OAAO,OAAA,CAAQ,IAAA;AAAA,EACxB;AAEA,EAAA,IAAI,OAAA,EAAS,UAAU,MAAA,EAAW;AAChC,IAAA,MAAA,CAAO,QAAQ,OAAA,CAAQ,KAAA;AAAA,EACzB;AAEA,EAAA,OAAO,MAAA;AACT;AA0BO,SAAS,QAAA,CACd,SAAA,EACA,SAAA,EACA,OAAA,EACkB;AAClB,EAAA,MAAM,GAAA,GAAmB,cAAc,KAAA,GAAQ,CAAC,UAAU,QAAQ,CAAA,GAAI,CAAC,SAAS,CAAA;AAEhF,EAAA,MAAM,MAAA,GAA2B;AAAA,IAC/B,IAAA,EAAM,UAAA;AAAA,IACN,SAAA,EAAW,GAAA;AAAA,IACX,SAAA;AAAA,IACA,QAAA,EAAU,SAAS,QAAA,IAAY;AAAA,GACjC;AAEA,EAAA,IAAI,OAAA,EAAS,SAAS,MAAA,EAAW;AAC/B,IAAA,MAAA,CAAO,OAAO,OAAA,CAAQ,IAAA;AAAA,EACxB;AAEA,EAAA,IAAI,OAAA,EAAS,UAAU,MAAA,EAAW;AAChC,IAAA,MAAA,CAAO,QAAQ,OAAA,CAAQ,KAAA;AAAA,EACzB;AAEA,EAAA,OAAO,MAAA;AACT;AClLO,IAAM,iBAAN,MAAmC;AAAA,EAChC,MAAA,uBAAa,GAAA,EAA+B;AAAA,EAC5C,QAAA,GAAW,KAAA;AAAA,EACX,MAAA;AAAA,EAER,WAAA,CAAY,QAAwB,OAAA,EAAqC;AACvE,IAAA,IAAA,CAAK,MAAA,GAAS,SAAS,MAAA,IAAU,YAAA;AACjC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAA,CAAK,WAAW,MAAM,CAAA;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,WAAW,MAAA,EAA6B;AACtC,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,MAAM,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACpD,MAAA,IAAI,CAAC,MAAA,EAAQ;AACb,MAAA,IAAA,CAAK,aAAA,CAAc,OAAO,MAAwB,CAAA;AAAA,IACpD;AACA,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAA,CAAc,OAAe,MAAA,EAA8B;AACzD,IAAA,MAAM,WAAA,GAAiC;AAAA,MACrC,QAAQ,EAAC;AAAA,MACT,QAAQ,EAAC;AAAA,MACT,SAAS,EAAC;AAAA,MACV,WAAW,EAAC;AAAA,MACZ,OAAA,EAAS,MAAA,CAAO,OAAA,IAAW,EAAC;AAAA,MAC5B,WAAA,EAAa,OAAO,WAAA,IAAe;AAAA,KACrC;AAGA,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AAC/C,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA;AAChC,MAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,MAAA,MAAM,aAAa,MAAA,CAAO,IAAA,IAAQ,CAAA,EAAG,KAAK,WAAW,CAAC,CAAA,CAAA;AAEtD,MAAA,IAAI;AACF,QAAA,IAAI,MAAA,CAAO,SAAS,QAAA,EAAU;AAC5B,UAAA,MAAM,QAAA,GAAW,IAAA,CAAK,mBAAA,CAAoB,MAAA,EAAQ,UAAU,CAAA;AAC5D,UAAA,WAAA,CAAY,OAAA,CAAQ,KAAK,QAAQ,CAAA;AAAA,QACnC,CAAA,MAAO;AACL,UAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,MAAA,EAAQ,UAAU,CAAA;AAEtD,UAAA,QAAQ,OAAO,IAAA;AAAM,YACnB,KAAK,OAAA;AACH,cAAA,WAAA,CAAY,MAAA,CAAO,KAAK,QAAQ,CAAA;AAChC,cAAA;AAAA,YACF,KAAK,MAAA;AACH,cAAA,WAAA,CAAY,MAAA,CAAO,KAAK,QAAQ,CAAA;AAChC,cAAA;AAAA,YACF,KAAK,UAAA;AACH,cAAA,WAAA,CAAY,SAAA,CAAU,KAAK,QAAQ,CAAA;AACnC,cAAA;AAAA;AACJ,QACF;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,MAAM,IAAI,cAAA;AAAA,UACR,CAAA,0BAAA,EAA6B,UAAU,CAAA,aAAA,EAAgB,KAAK,CAAA,GAAA,EAAM,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA;AAAA,UACxH,EAAE,KAAA,EAAO,MAAA,EAAQ,UAAA;AAAW,SAC9B;AAAA,MACF;AAAA,IACF;AAGA,IAAA,WAAA,CAAY,MAAA,CAAO,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,QAAA,GAAW,EAAE,QAAQ,CAAA;AACzD,IAAA,WAAA,CAAY,MAAA,CAAO,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,QAAA,GAAW,EAAE,QAAQ,CAAA;AACzD,IAAA,WAAA,CAAY,SAAA,CAAU,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,QAAA,GAAW,EAAE,QAAQ,CAAA;AAE5D,IAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAA,EAAO,WAAW,CAAA;AAAA,EACpC;AAAA,EAiBA,QAAA,CACE,aAAA,EACA,QAAA,EACA,OAAA,EAIM;AAEN,IAAA,IAAI,OAAO,aAAA,KAAkB,QAAA,IAAY,aAAA,KAAkB,IAAA,EAAM;AAC/D,MAAA,IAAA,CAAK,WAAW,aAAa,CAAA;AAC7B,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,KAAA,GAAQ,aAAA;AACd,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,cAAA,CAAe,sDAAA,EAAwD,EAAE,OAAO,CAAA;AAAA,IAC5F;AAEA,IAAA,MAAM,MAAA,GAAyB;AAAA,MAC7B;AAAA,KACF;AAEA,IAAA,IAAI,OAAA,EAAS,YAAY,MAAA,EAAW;AAClC,MAAA,MAAA,CAAO,UAAU,OAAA,CAAQ,OAAA;AAAA,IAC3B;AAEA,IAAA,IAAI,OAAA,EAAS,gBAAgB,MAAA,EAAW;AACtC,MAAA,MAAA,CAAO,cAAc,OAAA,CAAQ,WAAA;AAAA,IAC/B;AAEA,IAAA,IAAA,CAAK,aAAA,CAAc,OAAO,MAAM,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,aAAA,CAAc,QAA0B,IAAA,EAAsC;AACpF,IAAA,MAAM,UAAA,GAAa,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,SAAS,IAAI,MAAA,CAAO,SAAA,GAAY,CAAC,MAAA,CAAO,SAAS,CAAA;AAGzF,IAAA,MAAM,cAAc,UAAA,CAAW,OAAA;AAAA,MAAQ,CAAA,EAAA,KACrC,EAAA,KAAO,KAAA,GAAS,CAAC,MAAA,EAAQ,UAAU,QAAA,EAAU,QAAQ,CAAA,GAAc,CAAC,EAAE;AAAA,KACxE;AAEA,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,UAAA,EAAY,IAAI,GAAA,CAAI,WAAW,CAAA;AAAA,MAC/B,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,UAAU,MAAA,CAAO,SAAA;AAAA,MACjB,UAAU,MAAA,CAAO,QAAA,KAAa,MAAA,CAAO,IAAA,KAAS,SAAS,GAAA,GAAM,CAAA;AAAA,KAC/D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,mBAAA,CAAoB,QAA0B,IAAA,EAAoC;AACxF,IAAA,MAAM,YAAY,MAAA,CAAO,SAAA;AAEzB,IAAA,OAAO;AAAA,MACL,SAAA,EAAW,MAAA;AAAA,MACX,aAAA,EAAe,SAAA;AAAA,MACf;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,QAAA,EAAkD;AACzE,IAAA,OAAO;AAAA,MACL,MAAM,QAAA,CAAS,IAAA;AAAA,MACf,MAAM,QAAA,CAAS,IAAA;AAAA,MACf,SAAA,EAAW,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,UAAU,CAAA;AAAA,MACzC,UAAU,QAAA,CAAS,QAAA;AAAA,MACnB,UAAU,QAAA,CAAS;AAAA,KACrB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,CAAU,OAAe,SAAA,EAAwC;AAC/D,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AACpC,IAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,IAAA,OAAO,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,UAAA,CAAW,GAAA,CAAI,SAAS,CAAC,EAAE,GAAA,CAAI,CAAA,CAAA,KAAK,IAAA,CAAK,gBAAA,CAAiB,CAAC,CAAC,CAAA;AAAA,EACjG;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,CAAU,OAAe,SAAA,EAAwC;AAC/D,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AACpC,IAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,IAAA,OAAO,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,UAAA,CAAW,GAAA,CAAI,SAAS,CAAC,EAAE,GAAA,CAAI,CAAA,CAAA,KAAK,IAAA,CAAK,gBAAA,CAAiB,CAAC,CAAC,CAAA;AAAA,EACjG;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,CAAa,OAAe,SAAA,EAAwC;AAClE,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AACpC,IAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,IAAA,OAAO,MAAA,CAAO,SAAA,CACX,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,UAAA,CAAW,GAAA,CAAI,SAAS,CAAC,EACvC,GAAA,CAAI,CAAA,CAAA,KAAK,IAAA,CAAK,gBAAA,CAAiB,CAAC,CAAC,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,KAAA,EAAuC;AAChD,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AACpC,IAAA,OAAO,MAAA,EAAQ,WAAW,EAAC;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,KAAA,EAAyB;AAClC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AACpC,IAAA,OAAO,MAAA,EAAQ,WAAW,EAAC;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,KAAA,EAAwB;AACrC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AACpC,IAAA,OAAO,QAAQ,WAAA,IAAe,IAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,KAAA,EAAwB;AAC/B,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAAsB;AACpB,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAsB;AACpB,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,QAAA,GAAiB;AACf,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,MAAM,CAAA,IAAK,KAAK,MAAA,EAAQ;AAEzC,MAAA,MAAM,SAAA,GACJ,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,KACvB,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAA,IACvB,OAAO,OAAA,CAAQ,MAAA,GAAS,CAAA,IACxB,MAAA,CAAO,UAAU,MAAA,GAAS,CAAA;AAE5B,MAAA,IAAI,CAAC,SAAA,IAAa,CAAC,MAAA,CAAO,WAAA,EAAa;AAErC,QAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,UACV,gBAAgB,KAAK,CAAA,2EAAA;AAAA,SAEvB;AAAA,MACF;AAGA,MAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AAC7B,QAAA,MAAM,eAAA,uBAAsB,GAAA,EAAe;AAE3C,QAAA,KAAA,MAAWA,MAAAA,IAAS,OAAO,MAAA,EAAQ;AACjC,UAAAA,OAAM,UAAA,CAAW,OAAA,CAAQ,QAAM,eAAA,CAAgB,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,QACxD;AACA,QAAA,KAAA,MAAWC,KAAAA,IAAQ,OAAO,MAAA,EAAQ;AAChC,UAAAA,MAAK,UAAA,CAAW,OAAA,CAAQ,QAAM,eAAA,CAAgB,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,QACvD;AACA,QAAA,KAAA,MAAWC,SAAAA,IAAY,OAAO,SAAA,EAAW;AACvC,UAAAA,UAAS,UAAA,CAAW,OAAA,CAAQ,QAAM,eAAA,CAAgB,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,QAC3D;AACA,QAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AAC7B,UAAA,eAAA,CAAgB,IAAI,MAAM,CAAA;AAAA,QAC5B;AAEA,QAAA,MAAM,sBAAA,GAAyB,MAAA,CAAO,OAAA,CAAQ,MAAA,CAAO,CAAA,EAAA,KAAM;AAEzD,UAAA,IAAI,EAAA,KAAO,KAAA,EAAO,OAAO,eAAA,CAAgB,IAAA,GAAO,CAAA;AAEhD,UAAA,OAAO,eAAA,CAAgB,IAAI,EAAe,CAAA;AAAA,QAC5C,CAAC,CAAA;AAED,QAAA,IAAI,sBAAA,CAAuB,SAAS,CAAA,EAAG;AACrC,UAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,YACV,gBAAgB,KAAK,CAAA,kDAAA,EAAqD,sBAAA,CAAuB,IAAA,CAAK,IAAI,CAAC,CAAA,oDAAA;AAAA,WAE7G;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,OAAO,KAAA,EAAM;AAClB,IAAA,IAAA,CAAK,QAAA,GAAW,KAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,KAAA,EAAqB;AAC1B,IAAA,IAAA,CAAK,MAAA,CAAO,OAAO,KAAK,CAAA;AAAA,EAC1B;AACF;ACtYO,IAAM,UAAA,GAAa,IAAI,iBAAA,EAA8B;;;ACSrD,SAAS,iBACd,OAAA,EAC0B;AAC1B,EAAA,mBAAA,CAAoB,QAAQ,IAAI,CAAA;AAEhC,EAAA,MAAM,OAAA,GAAoC;AAAA,IACxC,IAAA,EAAM;AAAA,MACJ,GAAG,OAAA,CAAQ,IAAA;AAAA,MACX,QAAA,EAAU,OAAA,CAAQ,IAAA,CAAK,QAAA,IAAY;AAAA;AAAA,KACrC;AAAA,IACA,SAAA,sBAAe,IAAA;AAAK,GACtB;AAEA,EAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,IAAA,OAAA,CAAQ,OAAA,GAAU;AAAA,MAChB,GAAG,OAAA,CAAQ,OAAA;AAAA,MACX,SAAA,EAAW,OAAA,CAAQ,OAAA,CAAQ,SAAA,wBAAiB,IAAA;AAAK,KACnD;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAW;AAC9B,IAAA,OAAA,CAAQ,OAAO,OAAA,CAAQ,IAAA;AAAA,EACzB;AAEA,EAAA,OAAO,OAAA;AACT;AAKA,SAAS,oBAAoB,IAAA,EAA4B;AACvD,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,MAAA,IAAa,IAAA,CAAK,WAAW,IAAA,EAAM;AACrD,IAAA,MAAM,IAAI,yBAAA,CAA0B,oCAAA,EAAsC,QAAQ,CAAA;AAAA,EACpF;AAEA,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,yBAAA,CAA0B,wBAAA,EAA0B,OAAO,CAAA;AAAA,EACvE;AACF;AAMA,IAAM,oBAAN,MAAwB;AAAA;AAAA;AAAA;AAAA,EAItB,GAAA,CAAO,SAAqB,EAAA,EAAgB;AAC1C,IAAA,OAAO,UAAA,CAAW,GAAA,CAAI,OAAA,EAAS,EAAE,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAA,CAAY,OAAA,EAAqB,EAAA,EAAkC;AACvE,IAAA,OAAO,MAAM,UAAA,CAAW,GAAA,CAAI,OAAA,EAAS,EAAE,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAA,GAAyB;AACvB,IAAA,MAAM,GAAA,GAAM,WAAW,QAAA,EAAS;AAChC,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,MAAM,IAAI,eAAA,EAAgB;AAAA,IAC5B;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAA,GAAsC;AACpC,IAAA,OAAO,UAAA,CAAW,UAAS,IAAK,IAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAsB;AACpB,IAAA,OAAO,UAAA,CAAW,UAAS,KAAM,MAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAA,GAA0B;AACxB,IAAA,OAAO,IAAA,CAAK,YAAW,CAAE,IAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAA,GAA6B;AAC3B,IAAA,OAAO,IAAA,CAAK,SAAQ,CAAE,MAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAA,GAA2C;AACzC,IAAA,OAAO,IAAA,CAAK,SAAQ,CAAE,QAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,IAAA,EAAuB;AAC7B,IAAA,MAAM,GAAA,GAAM,KAAK,gBAAA,EAAiB;AAClC,IAAA,OAAO,GAAA,EAAK,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,IAAK,KAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,UAAA,EAA6B;AACzC,IAAA,MAAM,GAAA,GAAM,KAAK,gBAAA,EAAiB;AAClC,IAAA,OAAO,GAAA,EAAK,IAAA,CAAK,WAAA,EAAa,QAAA,CAAS,UAAU,CAAA,IAAK,KAAA;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA,GAAoB;AAClB,IAAA,MAAM,GAAA,GAAM,KAAK,gBAAA,EAAiB;AAClC,IAAA,OAAO,GAAA,EAAK,KAAK,QAAA,IAAY,KAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,SAAY,EAAA,EAAgB;AAC1B,IAAA,MAAM,UAAA,GAAa,KAAK,gBAAA,EAAiB;AACzC,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,IAAI,gBAAgB,uDAAuD,CAAA;AAAA,IACnF;AAEA,IAAA,MAAM,SAAA,GAAwB;AAAA,MAC5B,GAAG,UAAA;AAAA,MACH,MAAM,EAAE,GAAG,UAAA,CAAW,IAAA,EAAM,UAAU,IAAA;AAAK,KAC7C;AAEA,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,EAAE,CAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAiB,EAAA,EAAkC;AACvD,IAAA,MAAM,UAAA,GAAa,KAAK,gBAAA,EAAiB;AACzC,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,IAAI,gBAAgB,uDAAuD,CAAA;AAAA,IACnF;AAEA,IAAA,MAAM,SAAA,GAAwB;AAAA,MAC5B,GAAG,UAAA;AAAA,MACH,MAAM,EAAE,GAAG,UAAA,CAAW,IAAA,EAAM,UAAU,IAAA;AAAK,KAC7C;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,QAAA,CAAS,SAAA,EAAW,EAAE,CAAA;AAAA,EAC1C;AACF,CAAA;AAGO,IAAM,UAAA,GAAa,IAAI,iBAAA;AAKvB,SAAS,cAAA,CAAkB,SAAqB,EAAA,EAAgB;AACrE,EAAA,OAAO,UAAA,CAAW,GAAA,CAAI,OAAA,EAAS,EAAE,CAAA;AACnC;AAKA,eAAsB,mBAAA,CACpB,SACA,EAAA,EACY;AACZ,EAAA,OAAO,MAAM,UAAA,CAAW,QAAA,CAAS,OAAA,EAAS,EAAE,CAAA;AAC9C;ACxKO,SAAS,qBAAA,CAAsB,OAAe,MAAA,EAAwB;AAC3E,EAAA,OAAO,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AAC3B;AAcO,SAAS,mBAAA,CACd,EAAA,EACA,MAAA,EACA,QAAA,EACA,KAAA,EAC+B;AAC/B,EAAA,OAAO,EAAA,CAAG,KAAA,CAAM,MAAA,EAAe,QAAA,EAAiB,KAAY,CAAA;AAC9D;AAQO,SAAS,mBAAmB,UAAA,EAAyC;AAC1E,EAAA,OAAO,GAAA,CAAA,EAAM,GAAA,CAAI,GAAA,CAAI,UAAU,CAAC,CAAA,CAAA;AAClC;AAaO,SAAS,sBAAA,CACd,IACA,KAAA,EAC8E;AAC9E,EAAA,OAAO,EAAA,CAAG,UAAA,CAAW,KAAY,CAAA,CAAE,SAAA,EAAU;AAC/C;AAWO,SAAS,aAAA,CACd,EAAA,EACA,EAAA,EACA,gBAAA,GAAmB,IAAA,EACgB;AACnC,EAAA,OAAO,EAAA,CAAG,KAAA,CAAM,gBAAA,EAAyB,GAAA,EAAK,EAAS,CAAA;AACzD;AAcO,SAAS,qBAAA,CACd,EAAA,EACA,SAAA,EACA,SAAA,EAGI;AACJ,EAAA,IAAI,cAAc,QAAA,EAAU;AAC1B,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,WAAA,GAAc,UAAU,EAAS,CAAA;AACvC,EAAA,OAAO,WAAA;AACT;AAQO,SAAS,SACd,QAAA,EACkD;AAClD,EAAA,OAAO,SAAA,IAAa,QAAA,IAAa,QAAA,CAAiB,OAAA,KAAY,MAAA;AAChE;;;ACxHO,IAAM,oBAAN,MAAsC;AAAA,EAC3C,YAAoB,QAAA,EAA8B;AAA9B,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA,EAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBnD,SAAA,CACE,IACA,KAAA,EAC+B;AAE/B,IAAA,MAAM,GAAA,GAAM,WAAW,gBAAA,EAAiB;AACxC,IAAA,IAAI,CAAC,GAAA,EAAK;AAKR,MAAA,OAAO,mBAAA;AAAA,QACL,EAAA;AAAA,QACA,mBAAmB,OAAO,CAAA;AAAA,QAC1B,GAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAGA,IAAA,IAAI,GAAA,CAAI,KAAK,QAAA,EAAU;AACrB,MAAA,OAAO,EAAA;AAAA,IACT;AAGA,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,KAAK,CAAA;AAC9C,IAAA,IAAI,OAAA,CAAQ,KAAK,CAAA,IAAA,KAAQ,GAAA,CAAI,KAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA,EAAG;AACvD,MAAA,OAAO,EAAA;AAAA,IACT;AAGA,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,KAAK,CAAA;AAC9C,IAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,MAAA,OAAO,EAAA;AAAA,IACT;AAGA,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,KAAA,MAAWC,WAAU,OAAA,EAAS;AAC5B,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,cAAA,CAAeA,OAAAA,EAAQ,KAAK,KAAK,CAAA;AACzD,MAAA,MAAA,GAAS,IAAA,CAAK,eAAA,CAAgB,MAAA,EAAQ,UAAA,EAAY,KAAK,CAAA;AAAA,IACzD;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,cAAA,CACNA,OAAAA,EAMA,GAAA,EACA,KAAA,EACyB;AACzB,IAAA,MAAM,OAAA,GAAmC;AAAA,MACvC,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,GAAI,GAAA,CAAI,IAAA,KAAS,UAAa,EAAE,IAAA,EAAM,IAAI,IAAA;AAAgC,KAC5E;AAEA,IAAA,MAAM,MAAA,GAASA,OAAAA,CAAO,aAAA,CAAc,OAAO,CAAA;AAI3C,IAAA,IAAI,kBAAkB,OAAA,EAAS;AAC7B,MAAA,MAAM,IAAI,QAAA;AAAA,QACR,CAAA,wEAAA,EACaA,OAAAA,CAAO,IAAI,CAAA,YAAA,EAAe,KAAK,CAAA,qEAAA,CAAA;AAAA,QAE5C,aAAA,CAAc;AAAA,OAChB;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBQ,eAAA,CACN,EAAA,EACA,UAAA,EACA,KAAA,EAC+B;AAC/B,IAAA,IAAI,MAAA,GAAS,EAAA;AAEb,IAAA,KAAA,MAAW,CAAC,MAAA,EAAQ,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AAExD,MAAA,MAAM,eAAA,GAAkB,qBAAA,CAAsB,KAAA,EAAO,MAAM,CAAA;AAE3D,MAAA,IAAI,UAAU,IAAA,EAAM;AAElB,QAAA,MAAA,GAAS,mBAAA,CAAoB,MAAA,EAAQ,eAAA,EAAiB,IAAA,EAAM,IAAI,CAAA;AAAA,MAClE,CAAA,MAAA,IAAW,UAAU,MAAA,EAAW;AAE9B,QAAA;AAAA,MACF,CAAA,MAAA,IAAW,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC/B,QAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AAItB,UAAA,MAAA,GAAS,mBAAA;AAAA,YACP,MAAA;AAAA,YACA,mBAAmB,OAAO,CAAA;AAAA,YAC1B,GAAA;AAAA,YACA;AAAA,WACF;AAAA,QACF,CAAA,MAAO;AAEL,UAAA,MAAA,GAAS,mBAAA,CAAoB,MAAA,EAAQ,eAAA,EAAiB,IAAA,EAAM,KAAK,CAAA;AAAA,QACnE;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,MAAA,GAAS,mBAAA,CAAoB,MAAA,EAAQ,eAAA,EAAiB,GAAA,EAAK,KAAK,CAAA;AAAA,MAClE;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAA;;;ACtKA,IAAM,kBAAA,GAAqB,GAAA;AAMpB,IAAM,gBAAN,MAAkC;AAAA,EACvC,YAAoB,QAAA,EAA8B;AAA9B,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA,EAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAenD,MAAM,WAAA,CAAY,KAAA,EAAe,IAAA,EAA8C;AAC7E,IAAA,MAAM,IAAA,CAAK,aAAA,CAAc,KAAA,EAAO,QAAA,EAAU,QAAW,IAAI,CAAA;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,WAAA,CACJ,KAAA,EACA,WAAA,EACA,IAAA,EACe;AACf,IAAA,MAAM,IAAA,CAAK,aAAA,CAAc,KAAA,EAAO,QAAA,EAAU,aAAa,IAAI,CAAA;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,WAAA,CAAY,KAAA,EAAe,WAAA,EAAqD;AACpF,IAAA,MAAM,IAAA,CAAK,aAAA,CAAc,KAAA,EAAO,QAAA,EAAU,WAAW,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,SAAA,CAAU,KAAA,EAAe,GAAA,EAAgD;AAC7E,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,aAAA,CAAc,KAAA,EAAO,MAAA,EAAQ,GAAG,CAAA;AAC3C,MAAA,OAAO,IAAA;AAAA,IACT,SAAS,KAAA,EAAO;AAEd,MAAA,IAAI,KAAA,YAAiB,kBAAA,IAAsB,KAAA,YAAiB,wBAAA,EAA0B;AACpF,QAAA,OAAO,KAAA;AAAA,MACT;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,SAAA,CACJ,SAAA,EACA,KAAA,EACA,KACA,IAAA,EACkB;AAClB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,aAAA,CAAc,KAAA,EAAO,SAAA,EAAW,KAAK,IAAI,CAAA;AACpD,MAAA,OAAO,IAAA;AAAA,IACT,SAAS,KAAA,EAAO;AAEd,MAAA,IAAI,KAAA,YAAiB,kBAAA,IAAsB,KAAA,YAAiB,wBAAA,EAA0B;AACpF,QAAA,OAAO,KAAA;AAAA,MACT;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,gBAAA,CACJ,SAAA,EACA,KAAA,EACA,MACA,GAAA,EACkB;AAClB,IAAA,MAAM,GAAA,GAAM,WAAW,gBAAA,EAAiB;AACxC,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,IAAI,GAAA,CAAI,KAAK,QAAA,EAAU;AACrB,MAAA,OAAO,IAAA;AAAA,IACT;AAGA,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,KAAK,CAAA;AAC9C,IAAA,IAAI,OAAA,CAAQ,KAAK,CAAA,IAAA,KAAQ,GAAA,CAAI,KAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA,EAAG;AACvD,MAAA,OAAO,IAAA;AAAA,IACT;AAGA,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,QAAA,CAAS,YAAA,CAAa,OAAO,SAAS,CAAA;AAC7D,IAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC1B,MAAA,OAAO,IAAA;AAAA,IACT;AAGA,IAAA,MAAM,OAAA,GAAmC;AAAA,MACvC,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,GAAA;AAAA,MACA,IAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA;AAAA,MACA,GAAI,GAAA,CAAI,IAAA,KAAS,UAAa,EAAE,IAAA,EAAM,IAAI,IAAA;AAAgC,KAC5E;AAGA,IAAA,KAAA,MAAWD,aAAY,SAAA,EAAW;AAChC,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,CAAeA,UAAS,QAAA,EAAU,OAAA,EAASA,UAAS,IAAI,CAAA;AAClF,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,aAAA,CACZ,KAAA,EACA,SAAA,EACA,KACA,IAAA,EACe;AACf,IAAA,MAAM,GAAA,GAAM,WAAW,gBAAA,EAAiB;AACxC,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,MAAM,IAAI,kBAAA,CAAmB,SAAA,EAAW,KAAA,EAAO,0BAA0B,CAAA;AAAA,IAC3E;AAGA,IAAA,IAAI,GAAA,CAAI,KAAK,QAAA,EAAU;AACrB,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,KAAK,CAAA;AAC9C,IAAA,IAAI,OAAA,CAAQ,KAAK,CAAA,IAAA,KAAQ,GAAA,CAAI,KAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA,EAAG;AACvD,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,SAAA,CAAU,OAAO,SAAS,CAAA;AACvD,IAAA,KAAA,MAAWD,SAAQ,MAAA,EAAQ;AACzB,MAAA,MAAM,UAAU,IAAA,CAAK,iBAAA,CAAkB,KAAK,KAAA,EAAO,SAAA,EAAW,KAAK,IAAI,CAAA;AACvE,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,CAAeA,MAAK,QAAA,EAAU,OAAA,EAASA,MAAK,IAAI,CAAA;AAE1E,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,MAAM,IAAI,kBAAA,CAAmB,SAAA,EAAW,OAAO,CAAA,kBAAA,EAAqBA,KAAAA,CAAK,IAAI,CAAA,CAAE,CAAA;AAAA,MACjF;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,SAAA,KAAc,QAAA,IAAY,SAAA,KAAc,QAAA,KAAa,IAAA,EAAM;AAC9D,MAAA,MAAM,SAAA,GAAY,IAAA,CAAK,QAAA,CAAS,YAAA,CAAa,OAAO,SAAS,CAAA;AAC7D,MAAA,KAAA,MAAWC,aAAY,SAAA,EAAW;AAChC,QAAA,MAAM,UAAU,IAAA,CAAK,iBAAA,CAAkB,KAAK,KAAA,EAAO,SAAA,EAAW,KAAK,IAAI,CAAA;AACvE,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,CAAeA,UAAS,QAAA,EAAU,OAAA,EAASA,UAAS,IAAI,CAAA;AAElF,QAAA,IAAI,CAAC,MAAA,EAAQ;AACX,UAAA,MAAM,IAAI,kBAAA,CAAmB,SAAA,EAAW,OAAO,CAAA,mBAAA,EAAsBA,SAAAA,CAAS,IAAI,CAAA,CAAE,CAAA;AAAA,QACtF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,SAAA,CAAU,OAAO,SAAS,CAAA;AACvD,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,QAAA,CAAS,cAAA,CAAe,KAAK,CAAA;AAEtD,IAAA,IAAI,WAAA,IAAe,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AACtC,MAAA,MAAM,IAAI,kBAAA,CAAmB,SAAA,EAAW,KAAA,EAAO,0CAA0C,CAAA;AAAA,IAC3F;AAEA,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AAErB,MAAA,IAAI,OAAA,GAAU,KAAA;AAEd,MAAA,KAAA,MAAWF,UAAS,MAAA,EAAQ;AAC1B,QAAA,MAAM,UAAU,IAAA,CAAK,iBAAA,CAAkB,KAAK,KAAA,EAAO,SAAA,EAAW,KAAK,IAAI,CAAA;AACvE,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,CAAeA,OAAM,QAAA,EAAU,OAAA,EAASA,OAAM,IAAI,CAAA;AAE5E,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,OAAA,GAAU,IAAA;AACV,UAAA;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,kBAAA,CAAmB,SAAA,EAAW,KAAA,EAAO,2BAA2B,CAAA;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAA,CACN,GAAA,EACA,KAAA,EACA,SAAA,EACA,KACA,IAAA,EACyB;AACzB,IAAA,OAAO;AAAA,MACL,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,GAAA;AAAA,MACA,IAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA;AAAA,MACA,GAAI,GAAA,CAAI,IAAA,KAAS,UAAa,EAAE,IAAA,EAAM,IAAI,IAAA;AAAgC,KAC5E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,cAAA,CACZ,SAAA,EACA,OAAA,EACA,UAAA,EACkB;AAClB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,UAAU,OAAO,CAAA;AAChC,MAAA,OAAO,MAAA,YAAkB,OAAA,GAAU,MAAM,MAAA,GAAS,MAAA;AAAA,IACpD,SAAS,KAAA,EAAO;AAGd,MAAA,MAAM,aAAA,GAAgB,KAAA,YAAiB,KAAA,GAAQ,KAAA,GAAQ,MAAA;AACvD,MAAA,MAAM,IAAI,wBAAA;AAAA,QACR,QAAQ,SAAA,IAAa,SAAA;AAAA,QACrB,QAAQ,KAAA,IAAS,SAAA;AAAA,QACjB,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,eAAA;AAAA,QACzC,UAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,MAAM,UAAA,CACJ,KAAA,EACA,IAAA,EACA,YAAoB,kBAAA,EACN;AACd,IAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAE/B,IAAA,MAAM,UAAe,EAAC;AAGtB,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,KAAK,SAAA,EAAW;AAC/C,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,IAAI,SAAS,CAAA;AAGzC,MAAA,MAAM,YAAA,GAAe,MAAM,OAAA,CAAQ,GAAA;AAAA,QACjC,KAAA,CAAM,GAAA,CAAI,OAAO,GAAA,KAAQ;AACvB,UAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,SAAA,CAAU,OAAO,GAAG,CAAA;AAC/C,UAAA,OAAO,UAAU,GAAA,GAAM,IAAA;AAAA,QACzB,CAAC;AAAA,OACH;AAGA,MAAA,KAAA,MAAW,OAAO,YAAA,EAAc;AAC9B,QAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,UAAA,OAAA,CAAQ,KAAK,GAAG,CAAA;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AACF,CAAA;;;ACpXA,IAAM,WAAA,GAAc,aAAA;AACb,IAAM,OAAA,GAAU,WAAA,CAAY,UAAA,CAAW,IAAI,IAAI,WAAA,GAAc,WAAA;ACkG7D,IAAM,sBAAA,GAAyB,EAAE,MAAA,CAAO;AAAA,EAC7C,eAAe,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAQ,EAAE,QAAA,EAAS;AAAA,EAC5C,aAAa,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAQ,EAAE,QAAA,EAAS;AAAA,EAC1C,cAAA,EAAgB,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EACrC,sBAAA,EAAwB,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAC7C,cAAA,EAAgB,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EACrC,gBAAA,EAAkB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAC/B,CAAC;AAwDM,SAAS,UAAc,OAAA,EAAuC;AACnE,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,gBAAgB,EAAC;AAAA,IACjB,cAAc,EAAC;AAAA,IACf,MAAA,GAASI,YAAAA;AAAA,IACT,cAAA,GAAiB,IAAA;AAAA;AAAA,IACjB,sBAAA,GAAyB,KAAA;AAAA;AAAA,IACzB,cAAA,GAAiB,KAAA;AAAA,IACjB,WAAA;AAAA,IACA,gBAAA,GAAmB;AAAA,GACrB,GAAI,OAAA;AAGJ,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,iBAAA;AACJ,EAAA,IAAI,aAAA;AAEJ,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,aAAA;AAAA,IACN,OAAA,EAAS,OAAA;AAAA;AAAA,IAGT,QAAA,EAAU,EAAA;AAAA;AAAA,IAGV,cAAc,EAAC;AAAA;AAAA;AAAA;AAAA,IAKf,OAAY,SAAA,EAA8B;AACxC,MAAA,MAAA,CAAO,OAAO,+BAAA,EAAiC;AAAA,QAC7C,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA;AAAA,QAC5B,eAAe,aAAA,CAAc,MAAA;AAAA,QAC7B,aAAa,WAAA,CAAY;AAAA,OAC1B,CAAA;AAKD,MAAA,QAAA,GAAW,IAAI,eAAmB,MAAM,CAAA;AACxC,MAAA,QAAA,CAAS,QAAA,EAAS;AAGlB,MAAA,iBAAA,GAAoB,IAAI,kBAAsB,QAAQ,CAAA;AACtD,MAAA,aAAA,GAAgB,IAAI,cAAkB,QAAQ,CAAA;AAE9C,MAAA,MAAA,CAAO,OAAO,2CAA2C,CAAA;AAAA,IAC3D,CAAA;AAAA;AAAA;AAAA;AAAA,IAKA,MAAM,SAAA,GAA2B;AAE/B,MAAA,QAAA,CAAS,KAAA,EAAM;AACf,MAAA,MAAA,CAAO,OAAO,qDAAqD,CAAA;AAAA,IACrE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,cAAA,CAAmB,IAAQ,OAAA,EAAkC;AAC3D,MAAA,MAAM,EAAE,SAAA,EAAW,KAAA,EAAO,QAAA,EAAS,GAAI,OAAA;AAGvC,MAAA,IAAI,aAAA,CAAc,QAAA,CAAS,KAAK,CAAA,EAAG;AACjC,QAAA,MAAA,CAAO,KAAA,GAAQ,CAAA,uCAAA,EAA0C,KAAK,CAAA,CAAE,CAAA;AAChE,QAAA,OAAO,EAAA;AAAA,MACT;AAGA,MAAA,IAAI,QAAA,CAAS,SAAS,CAAA,KAAM,IAAA,EAAM;AAChC,QAAA,MAAA,CAAO,KAAA,GAAQ,CAAA,oCAAA,EAAuC,KAAK,CAAA,CAAE,CAAA;AAC7D,QAAA,OAAO,EAAA;AAAA,MACT;AAGA,MAAA,MAAM,GAAA,GAAM,WAAW,gBAAA,EAAiB;AAExC,MAAA,IAAI,CAAC,GAAA,EAAK;AAER,QAAA,IAAI,cAAA,EAAgB;AAClB,UAAA,MAAM,IAAI,eAAA;AAAA,YACR,CAAA,uCAAA,EAA0C,SAAS,CAAA,IAAA,EAAO,KAAK,CAAA,yJAAA;AAAA,WAGjE;AAAA,QACF;AAEA,QAAA,IAAI,CAAC,sBAAA,EAAwB;AAE3B,UAAA,MAAA,CAAO,IAAA;AAAA,YACL,CAAA,0BAAA,EAA6B,SAAS,CAAA,IAAA,EAAO,KAAK,CAAA,kIAAA;AAAA,WAGpD;AAEA,UAAA,IAAI,cAAc,QAAA,EAAU;AAC1B,YAAA,OAAO,qBAAA,CAAsB,EAAA,EAAI,SAAA,EAAW,CAAA,QAAA,KAAY;AAEtD,cAAA,OAAO,mBAAA;AAAA,gBACL,QAAA;AAAA,gBACA,mBAAmB,OAAO,CAAA;AAAA,gBAC1B,GAAA;AAAA,gBACA;AAAA,eACF;AAAA,YACF,CAAC,CAAA;AAAA,UACH;AAGA,UAAA,OAAO,EAAA;AAAA,QACT;AAGA,QAAA,MAAA,CAAO,IAAA;AAAA,UACL,CAAA,qBAAA,EAAwB,SAAS,CAAA,IAAA,EAAO,KAAK,CAAA,kGAAA;AAAA,SAG/C;AACA,QAAA,OAAO,EAAA;AAAA,MACT;AAGA,MAAA,IAAI,GAAA,CAAI,KAAK,QAAA,EAAU;AACrB,QAAA,MAAA,CAAO,KAAA,GAAQ,CAAA,mCAAA,EAAsC,KAAK,CAAA,CAAE,CAAA;AAC5D,QAAA,OAAO,EAAA;AAAA,MACT;AAGA,MAAA,IAAI,WAAA,CAAY,KAAK,CAAA,IAAA,KAAQ,GAAA,CAAI,KAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA,EAAG;AAC3D,QAAA,MAAA,CAAO,KAAA,GAAQ,CAAA,mCAAA,EAAsC,KAAK,CAAA,CAAE,CAAA;AAC5D,QAAA,OAAO,EAAA;AAAA,MACT;AAGA,MAAA,IAAI,cAAc,QAAA,EAAU;AAC1B,QAAA,IAAI;AACF,UAAA,MAAM,WAAA,GAAc,qBAAA;AAAA,YAClB,EAAA;AAAA,YACA,SAAA;AAAA;AAAA,YAEA,CAAA,QAAA,KAAY,iBAAA,CAAkB,SAAA,CAAU,QAAA,EAAiB,KAAK;AAAA,WAChE;AAEA,UAAA,IAAI,cAAA,EAAgB;AAClB,YAAA,MAAA,CAAO,OAAO,sBAAA,EAAwB;AAAA,cACpC,KAAA;AAAA,cACA,SAAA;AAAA,cACA,MAAA,EAAQ,IAAI,IAAA,CAAK;AAAA,aAClB,CAAA;AAAA,UACH;AAEA,UAAA,OAAO,WAAA;AAAA,QACT,SAAS,KAAA,EAAO;AACd,UAAA,MAAA,CAAO,KAAA,GAAQ,6BAAA,EAA+B,EAAE,KAAA,EAAO,OAAO,CAAA;AAC9D,UAAA,MAAM,KAAA;AAAA,QACR;AAAA,MACF;AAGA,MAAA,IAAI,SAAA,KAAc,QAAA,IAAY,SAAA,KAAc,QAAA,IAAY,cAAc,QAAA,EAAU;AAC9E,QAAA,QAAA,CAAS,eAAe,CAAA,GAAI,IAAA;AAC5B,QAAA,QAAA,CAAS,YAAY,CAAA,GAAI,KAAA;AAAA,MAC3B;AAEA,MAAA,OAAO,EAAA;AAAA,IACT,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,iBAAmC,IAAA,EAAY;AAE7C,MAAA,IAAI,CAAC,gBAAA,CAAiB,IAAI,CAAA,EAAG;AAC3B,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,MAAM,QAAA,GAAW,IAAA;AAEjB,MAAA,MAAM,QAAQ,QAAA,CAAS,SAAA;AAGvB,MAAA,IAAI,aAAA,CAAc,QAAA,CAAS,KAAK,CAAA,EAAG;AACjC,QAAA,MAAA,CAAO,KAAA,GAAQ,CAAA,wDAAA,EAA2D,KAAK,CAAA,CAAE,CAAA;AACjF,QAAA,OAAO,IAAA;AAAA,MACT;AAGA,MAAA,IAAI,CAAC,QAAA,CAAS,QAAA,CAAS,KAAK,CAAA,EAAG;AAC7B,QAAA,MAAA,CAAO,KAAA,GAAQ,CAAA,aAAA,EAAgB,KAAK,CAAA,6BAAA,CAA+B,CAAA;AACnE,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,MAAA,CAAO,KAAA,GAAQ,CAAA,sCAAA,EAAyC,KAAK,CAAA,CAAE,CAAA;AAG/D,MAAA,MAAM,cAAA,GAAiB,QAAA,CAAS,MAAA,EAAQ,IAAA,CAAK,QAAQ,CAAA;AACrD,MAAA,MAAM,cAAA,GAAiB,QAAA,CAAS,MAAA,EAAQ,IAAA,CAAK,QAAQ,CAAA;AACrD,MAAA,MAAM,cAAA,GAAiB,QAAA,CAAS,MAAA,EAAQ,IAAA,CAAK,QAAQ,CAAA;AACrD,MAAA,MAAM,gBAAA,GAAmB,QAAA,CAAS,QAAA,EAAU,IAAA,CAAK,QAAQ,CAAA;AAIzD,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA;AACxC,MAAA,MAAM,gBAAA,GAAmB,QAAA,CAAa,QAAA,CAAS,QAAQ,CAAA;AAEvD,MAAA,MAAM,YAAA,GAAe;AAAA,QACnB,GAAG,QAAA;AAAA;AAAA;AAAA;AAAA,QAKH,MAAM,OAAO,IAAA,EAAiC;AAC5C,UAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,YAAA,MAAM,IAAI,QAAA;AAAA,cACR,8CAAA;AAAA,cACA,aAAA,CAAc;AAAA,aAChB;AAAA,UACF;AAEA,UAAA,MAAM,GAAA,GAAM,WAAW,gBAAA,EAAiB;AAGxC,UAAA,IACE,GAAA,IACA,CAAC,GAAA,CAAI,IAAA,CAAK,YACV,CAAC,WAAA,CAAY,IAAA,CAAK,CAAA,IAAA,KAAQ,IAAI,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA,EACvD;AACA,YAAA,IAAI;AACF,cAAA,MAAM,aAAA,CAAc,WAAA,CAAY,KAAA,EAAO,IAA+B,CAAA;AAEtE,cAAA,IAAI,cAAA,EAAgB;AAClB,gBAAA,MAAA,CAAO,IAAA,GAAO,wBAAwB,EAAE,KAAA,EAAO,QAAQ,GAAA,CAAI,IAAA,CAAK,QAAQ,CAAA;AAAA,cAC1E;AAAA,YACF,SAAS,KAAA,EAAO;AACd,cAAA,IAAI,iBAAiB,kBAAA,EAAoB;AACvC,gBAAA,WAAA,GAAc,KAAK,CAAA;AACnB,gBAAA,IAAI,cAAA,EAAgB;AAClB,kBAAA,MAAA,CAAO,OAAO,qBAAA,EAAuB;AAAA,oBACnC,KAAA;AAAA,oBACA,MAAA,EAAQ,IAAI,IAAA,CAAK,MAAA;AAAA,oBACjB,QAAQ,KAAA,CAAM;AAAA,mBACf,CAAA;AAAA,gBACH;AAAA,cACF;AACA,cAAA,MAAM,KAAA;AAAA,YACR;AAAA,UACF;AAEA,UAAA,OAAO,MAAM,eAAe,IAAI,CAAA;AAAA,QAClC,CAAA;AAAA;AAAA;AAAA;AAAA,QAKA,MAAM,MAAA,CAAO,EAAA,EAAa,IAAA,EAAiC;AACzD,UAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,YAAA,MAAM,IAAI,QAAA;AAAA,cACR,8CAAA;AAAA,cACA,aAAA,CAAc;AAAA,aAChB;AAAA,UACF;AAEA,UAAA,MAAM,GAAA,GAAM,WAAW,gBAAA,EAAiB;AAExC,UAAA,IACE,GAAA,IACA,CAAC,GAAA,CAAI,IAAA,CAAK,YACV,CAAC,WAAA,CAAY,IAAA,CAAK,CAAA,IAAA,KAAQ,IAAI,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA,EACvD;AAGA,YAAA,IAAI,WAAA;AAEJ,YAAA,IAAI,gBAAA,EAAkB;AAEpB,cAAA,MAAM,KAAA,GAAQ,sBAAA,CAAuB,KAAA,EAAO,KAAK,CAAA;AACjD,cAAA,WAAA,GAAc,MAAM,aAAA,CAAc,KAAA,EAAO,EAAA,EAAI,gBAAgB,EAAE,gBAAA,EAAiB;AAAA,YAClF,WAAW,gBAAA,EAAkB;AAE3B,cAAA,WAAA,GAAc,MAAM,iBAAiB,EAAE,CAAA;AAAA,YACzC,CAAA,MAAO;AACL,cAAA,MAAM,IAAI,QAAA;AAAA,gBACR,8CAAA;AAAA,gBACA,aAAA,CAAc;AAAA,eAChB;AAAA,YACF;AAEA,YAAA,IAAI,CAAC,WAAA,EAAa;AAEhB,cAAA,OAAO,MAAM,cAAA,CAAe,EAAA,EAAI,IAAI,CAAA;AAAA,YACtC;AAEA,YAAA,IAAI;AACF,cAAA,MAAM,aAAA,CAAc,WAAA;AAAA,gBAClB,KAAA;AAAA,gBACA,WAAA;AAAA,gBACA;AAAA,eACF;AAEA,cAAA,IAAI,cAAA,EAAgB;AAClB,gBAAA,MAAA,CAAO,IAAA,GAAO,wBAAwB,EAAE,KAAA,EAAO,IAAI,MAAA,EAAQ,GAAA,CAAI,IAAA,CAAK,MAAA,EAAQ,CAAA;AAAA,cAC9E;AAAA,YACF,SAAS,KAAA,EAAO;AACd,cAAA,IAAI,iBAAiB,kBAAA,EAAoB;AACvC,gBAAA,WAAA,GAAc,KAAK,CAAA;AACnB,gBAAA,IAAI,cAAA,EAAgB;AAClB,kBAAA,MAAA,CAAO,OAAO,qBAAA,EAAuB;AAAA,oBACnC,KAAA;AAAA,oBACA,EAAA;AAAA,oBACA,MAAA,EAAQ,IAAI,IAAA,CAAK,MAAA;AAAA,oBACjB,QAAQ,KAAA,CAAM;AAAA,mBACf,CAAA;AAAA,gBACH;AAAA,cACF;AACA,cAAA,MAAM,KAAA;AAAA,YACR;AAAA,UACF;AAEA,UAAA,OAAO,MAAM,cAAA,CAAe,EAAA,EAAI,IAAI,CAAA;AAAA,QACtC,CAAA;AAAA;AAAA;AAAA;AAAA,QAKA,MAAM,OAAO,EAAA,EAA+B;AAC1C,UAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,YAAA,MAAM,IAAI,QAAA;AAAA,cACR,8CAAA;AAAA,cACA,aAAA,CAAc;AAAA,aAChB;AAAA,UACF;AAEA,UAAA,MAAM,GAAA,GAAM,WAAW,gBAAA,EAAiB;AAExC,UAAA,IACE,GAAA,IACA,CAAC,GAAA,CAAI,IAAA,CAAK,YACV,CAAC,WAAA,CAAY,IAAA,CAAK,CAAA,IAAA,KAAQ,IAAI,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA,EACvD;AAGA,YAAA,IAAI,WAAA;AAEJ,YAAA,IAAI,gBAAA,EAAkB;AAEpB,cAAA,MAAM,KAAA,GAAQ,sBAAA,CAAuB,KAAA,EAAO,KAAK,CAAA;AACjD,cAAA,WAAA,GAAc,MAAM,aAAA,CAAc,KAAA,EAAO,EAAA,EAAI,gBAAgB,EAAE,gBAAA,EAAiB;AAAA,YAClF,WAAW,gBAAA,EAAkB;AAE3B,cAAA,WAAA,GAAc,MAAM,iBAAiB,EAAE,CAAA;AAAA,YACzC,CAAA,MAAO;AACL,cAAA,MAAM,IAAI,QAAA;AAAA,gBACR,8CAAA;AAAA,gBACA,aAAA,CAAc;AAAA,eAChB;AAAA,YACF;AAEA,YAAA,IAAI,CAAC,WAAA,EAAa;AAEhB,cAAA,OAAO,MAAM,eAAe,EAAE,CAAA;AAAA,YAChC;AAEA,YAAA,IAAI;AACF,cAAA,MAAM,aAAA,CAAc,WAAA,CAAY,KAAA,EAAO,WAAsC,CAAA;AAE7E,cAAA,IAAI,cAAA,EAAgB;AAClB,gBAAA,MAAA,CAAO,IAAA,GAAO,wBAAwB,EAAE,KAAA,EAAO,IAAI,MAAA,EAAQ,GAAA,CAAI,IAAA,CAAK,MAAA,EAAQ,CAAA;AAAA,cAC9E;AAAA,YACF,SAAS,KAAA,EAAO;AACd,cAAA,IAAI,iBAAiB,kBAAA,EAAoB;AACvC,gBAAA,WAAA,GAAc,KAAK,CAAA;AACnB,gBAAA,IAAI,cAAA,EAAgB;AAClB,kBAAA,MAAA,CAAO,OAAO,qBAAA,EAAuB;AAAA,oBACnC,KAAA;AAAA,oBACA,EAAA;AAAA,oBACA,MAAA,EAAQ,IAAI,IAAA,CAAK,MAAA;AAAA,oBACjB,QAAQ,KAAA,CAAM;AAAA,mBACf,CAAA;AAAA,gBACH;AAAA,cACF;AACA,cAAA,MAAM,KAAA;AAAA,YACR;AAAA,UACF;AAEA,UAAA,OAAO,MAAM,eAAe,EAAE,CAAA;AAAA,QAChC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAcA,MAAM,WAAc,EAAA,EAAkC;AACpD,UAAA,OAAO,MAAM,UAAA,CAAW,aAAA,CAAc,EAAE,CAAA;AAAA,QAC1C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAcA,MAAM,SAAA,CAAU,SAAA,EAAsB,GAAA,EAAgD;AACpF,UAAA,MAAM,GAAA,GAAM,WAAW,gBAAA,EAAiB;AACxC,UAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AACjB,UAAA,IAAI,GAAA,CAAI,IAAA,CAAK,QAAA,EAAU,OAAO,IAAA;AAC9B,UAAA,IAAI,WAAA,CAAY,IAAA,CAAK,CAAA,IAAA,KAAQ,GAAA,CAAI,IAAA,CAAK,MAAM,QAAA,CAAS,IAAI,CAAC,CAAA,EAAG,OAAO,IAAA;AAEpE,UAAA,IAAI;AACF,YAAA,QAAQ,SAAA;AAAW,cACjB,KAAK,MAAA;AACH,gBAAA,OAAO,MAAM,aAAA,CAAc,SAAA,CAAU,KAAA,EAAO,GAAG,CAAA;AAAA,cACjD,KAAK,QAAA;AACH,gBAAA,MAAM,aAAA,CAAc,WAAA,CAAY,KAAA,EAAO,GAAG,CAAA;AAC1C,gBAAA,OAAO,IAAA;AAAA,cACT,KAAK,QAAA;AACH,gBAAA,MAAM,aAAA,CAAc,WAAA,CAAY,KAAA,EAAO,GAAA,EAAK,EAAE,CAAA;AAC9C,gBAAA,OAAO,IAAA;AAAA,cACT,KAAK,QAAA;AACH,gBAAA,MAAM,aAAA,CAAc,WAAA,CAAY,KAAA,EAAO,GAAG,CAAA;AAC1C,gBAAA,OAAO,IAAA;AAAA,cACT;AACE,gBAAA,OAAO,KAAA;AAAA;AACX,UACF,SAAS,KAAA,EAAO;AACd,YAAA,MAAA,CAAO,QAAQ,2BAAA,EAA6B;AAAA,cAC1C,KAAA;AAAA,cACA,SAAA;AAAA,cACA,OAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK;AAAA,aAC7D,CAAA;AACD,YAAA,OAAO,KAAA;AAAA,UACT;AAAA,QACF;AAAA,OACF;AAEA,MAAA,OAAO,YAAA;AAAA,IACT;AAAA,GACF;AACF;;;AC3mBO,SAAS,uBAAA,CACd,QACA,OAAA,EAI+C;AAC/C,EAAA,MAAM,GAAA,GAAqD;AAAA,IACzD,MAAM,MAAA,CAAO;AAAA,GACf;AAEA,EAAA,IAAI,OAAA,EAAS,QAAQ,MAAA,EAAW;AAC9B,IAAA,GAAA,CAAI,MAAM,OAAA,CAAQ,GAAA;AAAA,EACpB;AAEA,EAAA,IAAI,OAAA,EAAS,SAAS,MAAA,EAAW;AAC/B,IAAA,GAAA,CAAI,OAAO,OAAA,CAAQ,IAAA;AAAA,EACrB;AAEA,EAAA,IAAI,MAAA,CAAO,YAAY,MAAA,EAAW;AAChC,IAAA,GAAA,CAAI,UAAU,MAAA,CAAO,OAAA;AAAA,EACvB;AAEA,EAAA,IAAI,MAAA,CAAO,SAAS,MAAA,EAAW;AAC7B,IAAA,GAAA,CAAI,OAAO,MAAA,CAAO,IAAA;AAAA,EACpB;AAEA,EAAA,OAAO,GAAA;AACT;AASO,SAAS,gBAAgB,EAAA,EAA6D;AAC3F,EAAA,IAAI,EAAE,cAAc,QAAA,CAAA,EAAW;AAC7B,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,IAAI,EAAA,CAAG,WAAA,CAAY,IAAA,KAAS,eAAA,EAAiB;AAC3C,IAAA,OAAO,IAAA;AAAA,EACT;AAIA,EAAA,IAAI;AACF,IAAA,MAAM,SAAU,EAAA,EAAgB;AAChC,IAAA,OAAO,MAAA,YAAkB,OAAA;AAAA,EAC3B,CAAA,CAAA,MAAQ;AAGN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAKA,eAAsB,YAAA,CAAgB,IAA0B,YAAA,EAA6B;AAC3F,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,EAAA,EAAG;AAClB,IAAA,IAAI,kBAAkB,OAAA,EAAS;AAC7B,MAAA,OAAO,MAAM,MAAA;AAAA,IACf;AACA,IAAA,OAAO,MAAA;AAAA,EACT,SAAS,MAAA,EAAQ;AAGf,IAAA,OAAO,YAAA;AAAA,EACT;AACF;AAKO,SAAS,SAAA,CAA6C,QAAW,MAAA,EAAuB;AAC7F,EAAA,MAAM,MAAA,GAAS,EAAE,GAAG,MAAA,EAAO;AAE3B,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,EAAkB;AACpD,IAAA,MAAM,WAAA,GAAc,OAAO,GAAG,CAAA;AAC9B,IAAA,MAAM,WAAA,GAAc,OAAO,GAAG,CAAA;AAE9B,IAAA,IACE,WAAA,KAAgB,UAChB,OAAO,WAAA,KAAgB,YACvB,WAAA,KAAgB,IAAA,IAChB,CAAC,KAAA,CAAM,OAAA,CAAQ,WAAW,CAAA,IAC1B,OAAO,gBAAgB,QAAA,IACvB,WAAA,KAAgB,QAChB,CAAC,KAAA,CAAM,OAAA,CAAQ,WAAW,CAAA,EAC1B;AACA,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,SAAA;AAAA,QACZ,WAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,CAAA,MAAA,IAAW,gBAAgB,MAAA,EAAW;AACpC,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,WAAA;AAAA,IAChB;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAKO,SAAS,WAAW,GAAA,EAAqB;AAC9C,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,QAAQ,CAAA,EAAA,EAAK;AACnC,IAAA,MAAM,IAAA,GAAO,GAAA,CAAI,UAAA,CAAW,CAAC,CAAA;AAC7B,IAAA,IAAA,GAAA,CAAQ,IAAA,IAAQ,KAAK,IAAA,GAAO,IAAA;AAC5B,IAAA,IAAA,GAAO,IAAA,GAAO,IAAA;AAAA,EAChB;AACA,EAAA,OAAO,IAAA,CAAK,SAAS,EAAE,CAAA;AACzB;AAKO,SAAS,oBAAoB,SAAA,EAAiD;AACnF,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC5B,IAAA,IAAI,SAAA,CAAU,QAAA,CAAS,KAAK,CAAA,EAAG;AAC7B,MAAA,OAAO,CAAC,MAAA,EAAQ,QAAA,EAAU,QAAA,EAAU,QAAQ,CAAA;AAAA,IAC9C;AACA,IAAA,OAAO,SAAA;AAAA,EACT;AAEA,EAAA,IAAI,cAAc,KAAA,EAAO;AACvB,IAAA,OAAO,CAAC,MAAA,EAAQ,QAAA,EAAU,QAAA,EAAU,QAAQ,CAAA;AAAA,EAC9C;AAEA,EAAA,OAAO,CAAC,SAAS,CAAA;AACnB","file":"index.js","sourcesContent":["/**\n * RLS Error Classes\n *\n * This module provides specialized error classes for Row-Level Security operations.\n * All errors extend base error classes from @kysera/core for consistency across\n * the Kysera ecosystem.\n *\n * @module @kysera/rls/errors\n */\n\nimport { DatabaseError } from '@kysera/core'\nimport type { ErrorCode } from '@kysera/core'\n\n// ============================================================================\n// RLS Error Codes\n// ============================================================================\n\n/**\n * RLS-specific error codes\n *\n * These codes extend the unified error codes from @kysera/core with\n * RLS-specific error conditions.\n */\nexport const RLSErrorCodes = {\n /** RLS context is missing or not set */\n RLS_CONTEXT_MISSING: 'RLS_CONTEXT_MISSING' as ErrorCode,\n /** RLS policy violation occurred */\n RLS_POLICY_VIOLATION: 'RLS_POLICY_VIOLATION' as ErrorCode,\n /** RLS policy definition is invalid */\n RLS_POLICY_INVALID: 'RLS_POLICY_INVALID' as ErrorCode,\n /** RLS schema definition is invalid */\n RLS_SCHEMA_INVALID: 'RLS_SCHEMA_INVALID' as ErrorCode,\n /** RLS context validation failed */\n RLS_CONTEXT_INVALID: 'RLS_CONTEXT_INVALID' as ErrorCode,\n /** RLS policy evaluation threw an error */\n RLS_POLICY_EVALUATION_ERROR: 'RLS_POLICY_EVALUATION_ERROR' as ErrorCode\n} as const\n\n/**\n * Type for RLS error codes\n */\nexport type RLSErrorCode = (typeof RLSErrorCodes)[keyof typeof RLSErrorCodes]\n\n// ============================================================================\n// Base RLS Error\n// ============================================================================\n\n/**\n * Base class for all RLS-related errors\n *\n * Extends DatabaseError from @kysera/core for consistency with other Kysera packages.\n * Provides common error functionality including error codes and JSON serialization.\n *\n * @example\n * ```typescript\n * throw new RLSError('Something went wrong', RLSErrorCodes.RLS_POLICY_INVALID);\n * ```\n */\nexport class RLSError extends DatabaseError {\n /**\n * Creates a new RLS error\n *\n * @param message - Error message\n * @param code - RLS error code\n */\n constructor(message: string, code: RLSErrorCode) {\n super(message, code)\n this.name = 'RLSError'\n }\n}\n\n// ============================================================================\n// Context Errors\n// ============================================================================\n\n/**\n * Error thrown when RLS context is missing\n *\n * This error occurs when an operation requiring RLS context is executed\n * outside of a context scope (i.e., without calling withRLSContext()).\n *\n * @example\n * ```typescript\n * // This will throw RLSContextError\n * const result = await db.selectFrom('posts').execute();\n *\n * // Correct usage with context\n * await withRLSContext(rlsContext, async () => {\n * const result = await db.selectFrom('posts').execute();\n * });\n * ```\n */\nexport class RLSContextError extends RLSError {\n /**\n * Creates a new RLS context error\n *\n * @param message - Error message (defaults to standard message)\n */\n constructor(message = 'No RLS context found. Ensure code runs within withRLSContext()') {\n super(message, RLSErrorCodes.RLS_CONTEXT_MISSING)\n this.name = 'RLSContextError'\n }\n}\n\n/**\n * Error thrown when RLS context validation fails\n *\n * Extends RLSError as context validation failures are RLS-specific errors.\n *\n * This error occurs when the provided RLS context is invalid or missing\n * required fields.\n *\n * @example\n * ```typescript\n * // Missing required userId field\n * const invalidContext = {\n * auth: {\n * roles: ['user']\n * // userId is missing!\n * },\n * timestamp: new Date()\n * };\n *\n * // This will throw RLSContextValidationError\n * validateRLSContext(invalidContext);\n * ```\n */\nexport class RLSContextValidationError extends RLSError {\n public readonly field: string\n\n /**\n * Creates a new context validation error\n *\n * @param message - Error message\n * @param field - Field that failed validation\n */\n constructor(message: string, field: string) {\n super(message, RLSErrorCodes.RLS_CONTEXT_INVALID)\n this.name = 'RLSContextValidationError'\n this.field = field\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n field: this.field\n }\n }\n}\n\n// ============================================================================\n// Policy Errors\n// ============================================================================\n\n/**\n * Error thrown when an RLS policy violation occurs\n *\n * This error is thrown when a database operation is denied by RLS policies.\n * It provides detailed information about the violation including the operation,\n * table, and reason for denial.\n *\n * @example\n * ```typescript\n * // User tries to update a post they don't own\n * throw new RLSPolicyViolation(\n * 'update',\n * 'posts',\n * 'User does not own this post',\n * 'ownership_policy'\n * );\n * ```\n */\nexport class RLSPolicyViolation extends RLSError {\n public readonly operation: string\n public readonly table: string\n public readonly reason: string\n public readonly policyName?: string\n\n /**\n * Creates a new policy violation error\n *\n * @param operation - Database operation that was denied (read, create, update, delete)\n * @param table - Table name where violation occurred\n * @param reason - Reason for the policy violation\n * @param policyName - Name of the policy that denied access (optional)\n */\n constructor(operation: string, table: string, reason: string, policyName?: string) {\n super(\n `RLS policy violation: ${operation} on ${table} - ${reason}`,\n RLSErrorCodes.RLS_POLICY_VIOLATION\n )\n this.name = 'RLSPolicyViolation'\n this.operation = operation\n this.table = table\n this.reason = reason\n if (policyName !== undefined) {\n this.policyName = policyName\n }\n }\n\n override toJSON(): Record<string, unknown> {\n const json: Record<string, unknown> = {\n ...super.toJSON(),\n operation: this.operation,\n table: this.table,\n reason: this.reason\n }\n if (this.policyName !== undefined) {\n json['policyName'] = this.policyName\n }\n return json\n }\n}\n\n// ============================================================================\n// Policy Evaluation Errors\n// ============================================================================\n\n/**\n * Error thrown when a policy condition throws an error during evaluation\n *\n * This error is distinct from RLSPolicyViolation - it indicates a bug in the\n * policy condition function itself, not a legitimate access denial.\n *\n * @example\n * ```typescript\n * // A policy with a bug\n * allow('read', ctx => {\n * return ctx.row.someField.value; // Throws if someField is undefined\n * });\n *\n * // This will throw RLSPolicyEvaluationError, not RLSPolicyViolation\n * ```\n */\nexport class RLSPolicyEvaluationError extends RLSError {\n public readonly operation: string\n public readonly table: string\n public readonly policyName?: string\n public readonly originalError?: Error\n\n /**\n * Creates a new policy evaluation error\n *\n * @param operation - Database operation being performed\n * @param table - Table name where error occurred\n * @param message - Error message from the policy\n * @param policyName - Name of the policy that threw\n * @param originalError - The original error thrown by the policy\n */\n constructor(\n operation: string,\n table: string,\n message: string,\n policyName?: string,\n originalError?: Error\n ) {\n super(\n `RLS policy evaluation error during ${operation} on ${table}: ${message}`,\n RLSErrorCodes.RLS_POLICY_EVALUATION_ERROR\n )\n this.name = 'RLSPolicyEvaluationError'\n this.operation = operation\n this.table = table\n if (policyName !== undefined) {\n this.policyName = policyName\n }\n if (originalError !== undefined) {\n this.originalError = originalError\n // Preserve the original stack trace for debugging\n if (originalError.stack) {\n this.stack = `${this.stack}\\n\\nCaused by:\\n${originalError.stack}`\n }\n }\n }\n\n override toJSON(): Record<string, unknown> {\n const json: Record<string, unknown> = {\n ...super.toJSON(),\n operation: this.operation,\n table: this.table\n }\n if (this.policyName !== undefined) {\n json['policyName'] = this.policyName\n }\n if (this.originalError !== undefined) {\n json['originalError'] = {\n name: this.originalError.name,\n message: this.originalError.message\n }\n }\n return json\n }\n}\n\n// ============================================================================\n// Schema Errors\n// ============================================================================\n\n/**\n * Error thrown when RLS schema validation fails\n *\n * Extends RLSError as schema validation failures are RLS-specific errors.\n *\n * This error occurs when the RLS schema definition is invalid or contains\n * configuration errors.\n *\n * @example\n * ```typescript\n * // Invalid policy definition\n * const invalidSchema = {\n * posts: {\n * policies: [\n * {\n * type: 'invalid-type', // Invalid policy type!\n * operation: 'read',\n * condition: (ctx) => true\n * }\n * ]\n * }\n * };\n *\n * // This will throw RLSSchemaError\n * validateRLSSchema(invalidSchema);\n * ```\n */\nexport class RLSSchemaError extends RLSError {\n public readonly details: Record<string, unknown>\n\n /**\n * Creates a new schema validation error\n *\n * @param message - Error message\n * @param details - Additional details about the validation failure\n */\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(message, RLSErrorCodes.RLS_SCHEMA_INVALID)\n this.name = 'RLSSchemaError'\n this.details = details\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n details: this.details\n }\n }\n}\n","/**\n * RLS schema definition and validation\n *\n * Provides functions to define, validate, and merge RLS schemas.\n */\n\nimport type { RLSSchema, TableRLSConfig, PolicyDefinition } from './types.js'\nimport { RLSSchemaError } from '../errors.js'\n\n/**\n * Define RLS schema with full type safety\n *\n * @example\n * ```typescript\n * interface Database {\n * users: { id: number; email: string; tenant_id: number };\n * posts: { id: number; user_id: number; tenant_id: number };\n * }\n *\n * const schema = defineRLSSchema<Database>({\n * users: {\n * policies: [\n * // Users can read their own records\n * allow('read', ctx => ctx.auth.userId === ctx.row.id),\n * // Filter by tenant\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId })),\n * // Admins bypass all checks\n * allow('all', ctx => ctx.auth.roles.includes('admin')),\n * ],\n * },\n * posts: {\n * policies: [\n * // Filter posts by tenant\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId })),\n * // Users can only edit their own posts\n * allow(['update', 'delete'], ctx => ctx.auth.userId === ctx.row.user_id),\n * // Validate new posts belong to user's tenant\n * validate('create', ctx => ctx.data.tenant_id === ctx.auth.tenantId),\n * ],\n * defaultDeny: true, // Require explicit allow\n * },\n * });\n * ```\n */\nexport function defineRLSSchema<DB>(schema: RLSSchema<DB>): RLSSchema<DB> {\n // Validate schema\n validateSchema(schema)\n return schema\n}\n\n/**\n * Validate RLS schema\n * Throws RLSSchemaError if validation fails\n *\n * @internal\n */\nfunction validateSchema<DB>(schema: RLSSchema<DB>): void {\n for (const [table, config] of Object.entries(schema)) {\n if (!config) continue\n\n const tableConfig = config as TableRLSConfig\n\n if (!Array.isArray(tableConfig.policies)) {\n throw new RLSSchemaError(`Invalid policies for table \"${table}\": must be an array`, { table })\n }\n\n // Validate each policy\n for (let i = 0; i < tableConfig.policies.length; i++) {\n const policy = tableConfig.policies[i]\n if (policy !== undefined) {\n validatePolicy(policy, table, i)\n }\n }\n\n // Validate skipFor if present (array of role names that bypass RLS)\n if (tableConfig.skipFor !== undefined) {\n if (!Array.isArray(tableConfig.skipFor)) {\n throw new RLSSchemaError(\n `Invalid skipFor for table \"${table}\": must be an array of role names`,\n { table }\n )\n }\n\n // skipFor contains role names (strings), not operations\n for (const role of tableConfig.skipFor) {\n if (typeof role !== 'string' || role.trim() === '') {\n throw new RLSSchemaError(\n `Invalid role in skipFor for table \"${table}\": must be a non-empty string`,\n { table }\n )\n }\n }\n }\n\n // Validate defaultDeny if present\n if (tableConfig.defaultDeny !== undefined && typeof tableConfig.defaultDeny !== 'boolean') {\n throw new RLSSchemaError(`Invalid defaultDeny for table \"${table}\": must be a boolean`, {\n table\n })\n }\n }\n}\n\n/**\n * Validate a single policy\n * Throws RLSSchemaError if validation fails\n *\n * @internal\n */\nfunction validatePolicy(policy: PolicyDefinition, table: string, index: number): void {\n if (!policy.type) {\n throw new RLSSchemaError(`Policy ${index} for table \"${table}\" missing type`, { table, index })\n }\n\n const validTypes = ['allow', 'deny', 'filter', 'validate']\n if (!validTypes.includes(policy.type)) {\n throw new RLSSchemaError(\n `Policy ${index} for table \"${table}\" has invalid type: ${policy.type}`,\n { table, index, type: policy.type }\n )\n }\n\n if (!policy.operation) {\n throw new RLSSchemaError(`Policy ${index} for table \"${table}\" missing operation`, {\n table,\n index\n })\n }\n\n const validOps = ['read', 'create', 'update', 'delete', 'all']\n const ops = Array.isArray(policy.operation) ? policy.operation : [policy.operation]\n\n for (const op of ops) {\n if (!validOps.includes(op)) {\n throw new RLSSchemaError(\n `Policy ${index} for table \"${table}\" has invalid operation: ${op}`,\n { table, index, operation: op }\n )\n }\n }\n\n if (policy.condition === undefined || policy.condition === null) {\n throw new RLSSchemaError(`Policy ${index} for table \"${table}\" missing condition`, {\n table,\n index\n })\n }\n\n if (typeof policy.condition !== 'function' && typeof policy.condition !== 'string') {\n throw new RLSSchemaError(\n `Policy ${index} for table \"${table}\" condition must be a function or string`,\n { table, index }\n )\n }\n\n // Validate priority if present\n if (policy.priority !== undefined && typeof policy.priority !== 'number') {\n throw new RLSSchemaError(`Policy ${index} for table \"${table}\" priority must be a number`, {\n table,\n index\n })\n }\n\n // Validate name if present\n if (policy.name !== undefined && typeof policy.name !== 'string') {\n throw new RLSSchemaError(`Policy ${index} for table \"${table}\" name must be a string`, {\n table,\n index\n })\n }\n}\n\n/**\n * Merge multiple RLS schemas\n * Later schemas override earlier ones for the same table\n *\n * @example\n * ```typescript\n * const baseSchema = defineRLSSchema<Database>({\n * users: {\n * policies: [\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId })),\n * ],\n * },\n * });\n *\n * const adminSchema = defineRLSSchema<Database>({\n * users: {\n * policies: [\n * allow('all', ctx => ctx.auth.roles.includes('admin')),\n * ],\n * },\n * });\n *\n * // Merged schema will have both filters and admin allow\n * const merged = mergeRLSSchemas(baseSchema, adminSchema);\n * ```\n */\nexport function mergeRLSSchemas<DB>(...schemas: RLSSchema<DB>[]): RLSSchema<DB> {\n const merged: RLSSchema<DB> = {}\n\n for (const schema of schemas) {\n for (const [table, config] of Object.entries(schema)) {\n if (!config) continue\n\n const existingConfig = merged[table as keyof DB]\n const newConfig = config as TableRLSConfig\n\n if (existingConfig) {\n // Merge policies (append new policies)\n existingConfig.policies = [...existingConfig.policies, ...newConfig.policies]\n\n // Merge skipFor (combine arrays and deduplicate)\n if (newConfig.skipFor) {\n const existingSkipFor = existingConfig.skipFor ?? []\n const combinedSkipFor = [...existingSkipFor, ...newConfig.skipFor]\n existingConfig.skipFor = Array.from(new Set(combinedSkipFor))\n }\n\n // Override defaultDeny if explicitly set in new config\n if (newConfig.defaultDeny !== undefined) {\n existingConfig.defaultDeny = newConfig.defaultDeny\n }\n } else {\n // Deep copy the config to avoid mutation\n // Type cast necessary: TypeScript cannot infer that the spread object matches\n // the TableRLSConfig type exactly due to optional properties and type narrowing.\n // Runtime safety: We've validated the schema structure via validateSchema(),\n // and we're creating a proper TableRLSConfig from validated components.\n\n merged[table as keyof DB] = {\n policies: [...newConfig.policies],\n skipFor: newConfig.skipFor ? [...newConfig.skipFor] : undefined,\n defaultDeny: newConfig.defaultDeny\n } as TableRLSConfig\n }\n }\n }\n\n // Validate merged schema\n validateSchema(merged)\n\n return merged\n}\n","/**\n * Fluent policy builders for Row-Level Security\n *\n * Provides intuitive builder functions for creating RLS policies:\n * - allow: Grants access when condition is true\n * - deny: Blocks access when condition is true (overrides allow)\n * - filter: Adds WHERE conditions to SELECT queries\n * - validate: Validates mutation data before execution\n */\n\nimport type {\n Operation,\n PolicyDefinition,\n PolicyCondition,\n FilterCondition,\n PolicyHints\n} from './types.js'\n\n/**\n * Options for policy definitions\n */\nexport interface PolicyOptions {\n /** Policy name for debugging and identification */\n name?: string\n /** Priority (higher runs first, deny policies default to 100) */\n priority?: number\n /** Performance optimization hints */\n hints?: PolicyHints\n}\n\n/**\n * Create an allow policy\n * Grants access when condition evaluates to true\n *\n * @example\n * ```typescript\n * // Allow users to read their own records\n * allow('read', ctx => ctx.auth.userId === ctx.row.userId)\n *\n * // Allow admins to do everything\n * allow('all', ctx => ctx.auth.roles.includes('admin'))\n *\n * // Allow with multiple operations\n * allow(['read', 'update'], ctx => ctx.auth.userId === ctx.row.userId)\n *\n * // Named policy with priority\n * allow('read', ctx => ctx.auth.roles.includes('verified'), {\n * name: 'verified-users-only',\n * priority: 10\n * })\n * ```\n */\nexport function allow(\n operation: Operation | Operation[],\n condition: PolicyCondition,\n options?: PolicyOptions\n): PolicyDefinition {\n const policy: PolicyDefinition = {\n type: 'allow',\n operation,\n condition: condition,\n priority: options?.priority ?? 0\n }\n\n if (options?.name !== undefined) {\n policy.name = options.name\n }\n\n if (options?.hints !== undefined) {\n policy.hints = options.hints\n }\n\n return policy\n}\n\n/**\n * Create a deny policy\n * Blocks access when condition evaluates to true (overrides allow)\n * If no condition is provided, always denies\n *\n * @example\n * ```typescript\n * // Deny access to banned users\n * deny('all', ctx => ctx.auth.attributes?.banned === true)\n *\n * // Deny deletions on archived records\n * deny('delete', ctx => ctx.row.archived === true)\n *\n * // Deny all access to sensitive table\n * deny('all')\n *\n * // Named deny with high priority\n * deny('all', ctx => ctx.auth.attributes?.suspended === true, {\n * name: 'block-suspended-users',\n * priority: 200\n * })\n * ```\n */\nexport function deny(\n operation: Operation | Operation[],\n condition?: PolicyCondition,\n options?: PolicyOptions\n): PolicyDefinition {\n const policy: PolicyDefinition = {\n type: 'deny',\n operation,\n condition: condition ?? (() => true),\n priority: options?.priority ?? 100 // Deny policies run first by default\n }\n\n if (options?.name !== undefined) {\n policy.name = options.name\n }\n\n if (options?.hints !== undefined) {\n policy.hints = options.hints\n }\n\n return policy\n}\n\n/**\n * Create a filter policy\n * Adds WHERE conditions to SELECT queries\n *\n * **IMPORTANT**: Filter conditions must be synchronous functions.\n * Async filter policies are not currently supported because filters are applied\n * directly to query builders at query construction time.\n *\n * @example\n * ```typescript\n * // ✅ CORRECT: Filter by tenant (synchronous)\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId }))\n *\n * // ✅ CORRECT: Filter by organization with soft delete\n * filter('read', ctx => ({\n * organization_id: ctx.auth.organizationIds?.[0],\n * deleted_at: null\n * }))\n *\n * // ❌ WRONG: Async filter (not supported)\n * // filter('read', async ctx => {\n * // const tenantId = await fetchTenantId(ctx.auth.userId)\n * // return { tenant_id: tenantId }\n * // })\n *\n * // ✅ WORKAROUND: Fetch data before creating context\n * // const tenantId = await fetchTenantId(userId)\n * // const ctx = createRLSContext({ auth: { userId, tenantId, roles: [] } })\n * // filter('read', ctx => ({ tenant_id: ctx.auth.tenantId }))\n *\n * // Named filter\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId }), {\n * name: 'tenant-filter'\n * })\n * ```\n */\nexport function filter(\n operation: 'read' | 'all',\n condition: FilterCondition,\n options?: PolicyOptions\n): PolicyDefinition {\n const policy: PolicyDefinition = {\n type: 'filter',\n operation: operation === 'all' ? 'read' : operation,\n condition: condition as unknown as PolicyCondition,\n priority: options?.priority ?? 0\n }\n\n if (options?.name !== undefined) {\n policy.name = options.name\n }\n\n if (options?.hints !== undefined) {\n policy.hints = options.hints\n }\n\n return policy\n}\n\n/**\n * Create a validate policy\n * Validates mutation data before execution\n *\n * @example\n * ```typescript\n * // Validate user can only set their own user_id\n * validate('create', ctx => ctx.data.userId === ctx.auth.userId)\n *\n * // Validate status transitions\n * validate('update', ctx => {\n * const { status } = ctx.data;\n * return !status || ['draft', 'published'].includes(status);\n * })\n *\n * // Apply to both create and update\n * validate('all', ctx => ctx.data.price >= 0)\n *\n * // Named validation\n * validate('create', ctx => validateEmail(ctx.data.email), {\n * name: 'validate-email'\n * })\n * ```\n */\nexport function validate(\n operation: 'create' | 'update' | 'all',\n condition: PolicyCondition,\n options?: PolicyOptions\n): PolicyDefinition {\n const ops: Operation[] = operation === 'all' ? ['create', 'update'] : [operation]\n\n const policy: PolicyDefinition = {\n type: 'validate',\n operation: ops,\n condition: condition,\n priority: options?.priority ?? 0\n }\n\n if (options?.name !== undefined) {\n policy.name = options.name\n }\n\n if (options?.hints !== undefined) {\n policy.hints = options.hints\n }\n\n return policy\n}\n","/**\n * Policy Registry\n * Central registry for managing RLS policies across all tables\n *\n * The PolicyRegistry compiles and stores RLS policies for efficient runtime lookup.\n * It categorizes policies by type (allow/deny/filter/validate) and operation,\n * and provides methods to query policies for specific tables and operations.\n */\n\nimport type {\n Operation,\n PolicyDefinition,\n FilterCondition,\n RLSSchema,\n TableRLSConfig,\n CompiledPolicy,\n CompiledFilterPolicy,\n PolicyEvaluationContext\n} from './types.js'\nimport { RLSSchemaError } from '../errors.js'\nimport { silentLogger, type KyseraLogger } from '@kysera/core'\n\n/**\n * Internal compiled policy with operations as Set for efficient lookup\n */\ninterface InternalCompiledPolicy {\n name: string\n operations: Set<Operation>\n type: 'allow' | 'deny' | 'validate'\n evaluate: (ctx: PolicyEvaluationContext) => boolean | Promise<boolean>\n priority: number\n}\n\n/**\n * Table policy configuration\n */\ninterface TablePolicyConfig {\n allows: InternalCompiledPolicy[]\n denies: InternalCompiledPolicy[]\n filters: CompiledFilterPolicy[]\n validates: InternalCompiledPolicy[]\n skipFor: string[] // Role names that bypass RLS\n defaultDeny: boolean\n}\n\n/**\n * Policy Registry\n * Manages and provides access to RLS policies\n */\nexport class PolicyRegistry<DB = unknown> {\n private tables = new Map<string, TablePolicyConfig>()\n private compiled = false\n private logger: KyseraLogger\n\n constructor(schema?: RLSSchema<DB>, options?: { logger?: KyseraLogger }) {\n this.logger = options?.logger ?? silentLogger\n if (schema) {\n this.loadSchema(schema)\n }\n }\n\n /**\n * Load and compile policies from schema\n *\n * @example\n * ```typescript\n * const registry = new PolicyRegistry<Database>();\n * registry.loadSchema({\n * users: {\n * policies: [\n * allow('read', ctx => ctx.auth.userId === ctx.row.id),\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId })),\n * ],\n * defaultDeny: true,\n * },\n * });\n * ```\n */\n loadSchema(schema: RLSSchema<DB>): void {\n for (const [table, config] of Object.entries(schema)) {\n if (!config) continue\n this.registerTable(table, config as TableRLSConfig)\n }\n this.compiled = true\n }\n\n /**\n * Register policies for a single table\n *\n * @param table - Table name\n * @param config - Table RLS configuration\n */\n registerTable(table: string, config: TableRLSConfig): void {\n const tableConfig: TablePolicyConfig = {\n allows: [],\n denies: [],\n filters: [],\n validates: [],\n skipFor: config.skipFor ?? [],\n defaultDeny: config.defaultDeny ?? true\n }\n\n // Compile and categorize policies\n for (let i = 0; i < config.policies.length; i++) {\n const policy = config.policies[i]\n if (!policy) continue\n\n const policyName = policy.name ?? `${table}_policy_${i}`\n\n try {\n if (policy.type === 'filter') {\n const compiled = this.compileFilterPolicy(policy, policyName)\n tableConfig.filters.push(compiled)\n } else {\n const compiled = this.compilePolicy(policy, policyName)\n\n switch (policy.type) {\n case 'allow':\n tableConfig.allows.push(compiled)\n break\n case 'deny':\n tableConfig.denies.push(compiled)\n break\n case 'validate':\n tableConfig.validates.push(compiled)\n break\n }\n }\n } catch (error) {\n throw new RLSSchemaError(\n `Failed to compile policy \"${policyName}\" for table \"${table}\": ${error instanceof Error ? error.message : String(error)}`,\n { table, policy: policyName }\n )\n }\n }\n\n // Sort by priority (higher priority first)\n tableConfig.allows.sort((a, b) => b.priority - a.priority)\n tableConfig.denies.sort((a, b) => b.priority - a.priority)\n tableConfig.validates.sort((a, b) => b.priority - a.priority)\n\n this.tables.set(table, tableConfig)\n }\n\n /**\n * Register policies - supports both schema and table-based registration\n *\n * @overload Register a full schema\n * @overload Register policies for a single table (deprecated)\n */\n register(schemaOrTable: RLSSchema<DB>): void\n register(\n schemaOrTable: keyof DB & string,\n policies: PolicyDefinition[],\n options?: {\n skipFor?: string[]\n defaultDeny?: boolean\n }\n ): void\n register(\n schemaOrTable: RLSSchema<DB> | (keyof DB & string),\n policies?: PolicyDefinition[],\n options?: {\n skipFor?: string[] // Role names that bypass RLS\n defaultDeny?: boolean\n }\n ): void {\n // If first argument is an object with policies, treat as schema\n if (typeof schemaOrTable === 'object' && schemaOrTable !== null) {\n this.loadSchema(schemaOrTable)\n return\n }\n\n // Otherwise, treat as table-based registration\n const table = schemaOrTable\n if (!policies) {\n throw new RLSSchemaError('Policies are required when registering by table name', { table })\n }\n\n const config: TableRLSConfig = {\n policies\n }\n\n if (options?.skipFor !== undefined) {\n config.skipFor = options.skipFor\n }\n\n if (options?.defaultDeny !== undefined) {\n config.defaultDeny = options.defaultDeny\n }\n\n this.registerTable(table, config)\n }\n\n /**\n * Compile a policy definition into an internal compiled policy\n *\n * @param policy - Policy definition to compile\n * @param name - Policy name for debugging\n * @returns Compiled policy ready for evaluation\n */\n private compilePolicy(policy: PolicyDefinition, name: string): InternalCompiledPolicy {\n const operations = Array.isArray(policy.operation) ? policy.operation : [policy.operation]\n\n // Expand 'all' to all operations\n const expandedOps = operations.flatMap(op =>\n op === 'all' ? (['read', 'create', 'update', 'delete'] as const) : [op]\n ) as Operation[]\n\n return {\n name,\n operations: new Set(expandedOps),\n type: policy.type as 'allow' | 'deny' | 'validate',\n evaluate: policy.condition as (ctx: PolicyEvaluationContext) => boolean | Promise<boolean>,\n priority: policy.priority ?? (policy.type === 'deny' ? 100 : 0)\n }\n }\n\n /**\n * Compile a filter policy\n *\n * @param policy - Filter policy definition\n * @param name - Policy name for debugging\n * @returns Compiled filter policy\n */\n private compileFilterPolicy(policy: PolicyDefinition, name: string): CompiledFilterPolicy {\n const condition = policy.condition as unknown as FilterCondition\n\n return {\n operation: 'read',\n getConditions: condition as (ctx: PolicyEvaluationContext) => Record<string, unknown>,\n name\n }\n }\n\n /**\n * Convert internal compiled policy to public CompiledPolicy\n */\n private toCompiledPolicy(internal: InternalCompiledPolicy): CompiledPolicy {\n return {\n name: internal.name,\n type: internal.type,\n operation: Array.from(internal.operations),\n evaluate: internal.evaluate,\n priority: internal.priority\n }\n }\n\n /**\n * Get allow policies for a table and operation\n */\n getAllows(table: string, operation: Operation): CompiledPolicy[] {\n const config = this.tables.get(table)\n if (!config) return []\n\n return config.allows.filter(p => p.operations.has(operation)).map(p => this.toCompiledPolicy(p))\n }\n\n /**\n * Get deny policies for a table and operation\n */\n getDenies(table: string, operation: Operation): CompiledPolicy[] {\n const config = this.tables.get(table)\n if (!config) return []\n\n return config.denies.filter(p => p.operations.has(operation)).map(p => this.toCompiledPolicy(p))\n }\n\n /**\n * Get validate policies for a table and operation\n */\n getValidates(table: string, operation: Operation): CompiledPolicy[] {\n const config = this.tables.get(table)\n if (!config) return []\n\n return config.validates\n .filter(p => p.operations.has(operation))\n .map(p => this.toCompiledPolicy(p))\n }\n\n /**\n * Get filter policies for a table\n */\n getFilters(table: string): CompiledFilterPolicy[] {\n const config = this.tables.get(table)\n return config?.filters ?? []\n }\n\n /**\n * Get roles that skip RLS for a table\n */\n getSkipFor(table: string): string[] {\n const config = this.tables.get(table)\n return config?.skipFor ?? []\n }\n\n /**\n * Check if table has default deny\n */\n hasDefaultDeny(table: string): boolean {\n const config = this.tables.get(table)\n return config?.defaultDeny ?? true\n }\n\n /**\n * Check if a table is registered\n */\n hasTable(table: string): boolean {\n return this.tables.has(table)\n }\n\n /**\n * Get all registered table names\n */\n getTables(): string[] {\n return Array.from(this.tables.keys())\n }\n\n /**\n * Check if registry is compiled\n */\n isCompiled(): boolean {\n return this.compiled\n }\n\n /**\n * Validate that all policies are properly defined\n *\n * This method checks for common issues:\n * - Tables with no policies and defaultDeny=false (warns)\n * - Tables with skipFor operations but no corresponding policies\n */\n validate(): void {\n for (const [table, config] of this.tables) {\n // Check that at least one operation has policies\n const hasPolicy =\n config.allows.length > 0 ||\n config.denies.length > 0 ||\n config.filters.length > 0 ||\n config.validates.length > 0\n\n if (!hasPolicy && !config.defaultDeny) {\n // Warning: table has no policies and defaultDeny is false\n this.logger.warn?.(\n `[RLS] Table \"${table}\" has no policies and defaultDeny is false. ` +\n `All operations will be allowed.`\n )\n }\n\n // Warn if skipFor includes operations that have policies\n if (config.skipFor.length > 0) {\n const opsWithPolicies = new Set<Operation>()\n\n for (const allow of config.allows) {\n allow.operations.forEach(op => opsWithPolicies.add(op))\n }\n for (const deny of config.denies) {\n deny.operations.forEach(op => opsWithPolicies.add(op))\n }\n for (const validate of config.validates) {\n validate.operations.forEach(op => opsWithPolicies.add(op))\n }\n if (config.filters.length > 0) {\n opsWithPolicies.add('read')\n }\n\n const skippedOpsWithPolicies = config.skipFor.filter(op => {\n // 'all' means skip all operations\n if (op === 'all') return opsWithPolicies.size > 0\n // Check if this is an operation name (for backwards compatibility)\n return opsWithPolicies.has(op as Operation)\n })\n\n if (skippedOpsWithPolicies.length > 0) {\n this.logger.warn?.(\n `[RLS] Table \"${table}\" has skipFor operations that also have policies: ${skippedOpsWithPolicies.join(', ')}. ` +\n `The policies will be ignored for these operations.`\n )\n }\n }\n }\n }\n\n /**\n * Clear all policies\n */\n clear(): void {\n this.tables.clear()\n this.compiled = false\n }\n\n /**\n * Remove policies for a specific table\n */\n remove(table: string): void {\n this.tables.delete(table)\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { RLSContext } from './types.js'\n\n/**\n * AsyncLocalStorage instance for RLS context\n * Provides automatic context propagation across async boundaries\n */\nexport const rlsStorage = new AsyncLocalStorage<RLSContext>()\n","import { rlsStorage } from './storage.js'\nimport type { RLSContext, RLSAuthContext, RLSRequestContext } from './types.js'\nimport { RLSContextError, RLSContextValidationError } from '../errors.js'\n\n/**\n * Options for creating RLS context\n */\nexport interface CreateRLSContextOptions<TUser = unknown, TMeta = unknown> {\n auth: RLSAuthContext<TUser>\n request?: Partial<RLSRequestContext>\n meta?: TMeta\n}\n\n/**\n * Create a new RLS context\n */\nexport function createRLSContext<TUser = unknown, TMeta = unknown>(\n options: CreateRLSContextOptions<TUser, TMeta>\n): RLSContext<TUser, TMeta> {\n validateAuthContext(options.auth)\n\n const context: RLSContext<TUser, TMeta> = {\n auth: {\n ...options.auth,\n isSystem: options.auth.isSystem ?? false // Default to false if not provided\n },\n timestamp: new Date()\n }\n\n if (options.request) {\n context.request = {\n ...options.request,\n timestamp: options.request.timestamp ?? new Date()\n } as RLSRequestContext\n }\n\n if (options.meta !== undefined) {\n context.meta = options.meta\n }\n\n return context\n}\n\n/**\n * Validate auth context\n */\nfunction validateAuthContext(auth: RLSAuthContext): void {\n if (auth.userId === undefined || auth.userId === null) {\n throw new RLSContextValidationError('userId is required in auth context', 'userId')\n }\n\n if (!Array.isArray(auth.roles)) {\n throw new RLSContextValidationError('roles must be an array', 'roles')\n }\n}\n\n/**\n * RLS Context Manager\n * Manages RLS context using AsyncLocalStorage for automatic propagation\n */\nclass RLSContextManager {\n /**\n * Run a synchronous function within an RLS context\n */\n run<T>(context: RLSContext, fn: () => T): T {\n return rlsStorage.run(context, fn)\n }\n\n /**\n * Run an async function within an RLS context\n */\n async runAsync<T>(context: RLSContext, fn: () => Promise<T>): Promise<T> {\n return await rlsStorage.run(context, fn)\n }\n\n /**\n * Get current RLS context\n * @throws RLSContextError if no context is set\n */\n getContext(): RLSContext {\n const ctx = rlsStorage.getStore()\n if (!ctx) {\n throw new RLSContextError()\n }\n return ctx\n }\n\n /**\n * Get current RLS context or null if not set\n */\n getContextOrNull(): RLSContext | null {\n return rlsStorage.getStore() ?? null\n }\n\n /**\n * Check if running within RLS context\n */\n hasContext(): boolean {\n return rlsStorage.getStore() !== undefined\n }\n\n /**\n * Get current auth context\n * @throws RLSContextError if no context is set\n */\n getAuth(): RLSAuthContext {\n return this.getContext().auth\n }\n\n /**\n * Get current user ID\n * @throws RLSContextError if no context is set\n */\n getUserId(): string | number {\n return this.getAuth().userId\n }\n\n /**\n * Get current tenant ID\n * @throws RLSContextError if no context is set\n */\n getTenantId(): string | number | undefined {\n return this.getAuth().tenantId\n }\n\n /**\n * Check if current user has a specific role\n */\n hasRole(role: string): boolean {\n const ctx = this.getContextOrNull()\n return ctx?.auth.roles.includes(role) ?? false\n }\n\n /**\n * Check if current user has a specific permission\n */\n hasPermission(permission: string): boolean {\n const ctx = this.getContextOrNull()\n return ctx?.auth.permissions?.includes(permission) ?? false\n }\n\n /**\n * Check if current context is a system context (bypasses RLS)\n */\n isSystem(): boolean {\n const ctx = this.getContextOrNull()\n return ctx?.auth.isSystem ?? false\n }\n\n /**\n * Create a system context for operations that should bypass RLS\n */\n asSystem<T>(fn: () => T): T {\n const currentCtx = this.getContextOrNull()\n if (!currentCtx) {\n throw new RLSContextError('Cannot create system context without existing context')\n }\n\n const systemCtx: RLSContext = {\n ...currentCtx,\n auth: { ...currentCtx.auth, isSystem: true }\n }\n\n return this.run(systemCtx, fn)\n }\n\n /**\n * Create a system context for async operations\n */\n async asSystemAsync<T>(fn: () => Promise<T>): Promise<T> {\n const currentCtx = this.getContextOrNull()\n if (!currentCtx) {\n throw new RLSContextError('Cannot create system context without existing context')\n }\n\n const systemCtx: RLSContext = {\n ...currentCtx,\n auth: { ...currentCtx.auth, isSystem: true }\n }\n\n return await this.runAsync(systemCtx, fn)\n }\n}\n\n// Export singleton instance\nexport const rlsContext = new RLSContextManager()\n\n/**\n * Convenience function to run code within RLS context\n */\nexport function withRLSContext<T>(context: RLSContext, fn: () => T): T {\n return rlsContext.run(context, fn)\n}\n\n/**\n * Convenience function to run async code within RLS context\n */\nexport async function withRLSContextAsync<T>(\n context: RLSContext,\n fn: () => Promise<T>\n): Promise<T> {\n return await rlsContext.runAsync(context, fn)\n}\n","/**\n * Type utilities for RLS plugin\n *\n * These utilities provide type-safe wrappers around dynamic operations\n * that require runtime flexibility beyond TypeScript's compile-time constraints.\n *\n * NOTE: This file intentionally uses `any` types to bridge the gap between\n * Kysely's compile-time type system and RLS's runtime dynamic requirements.\n * All `any` usage is documented and justified with runtime safety guarantees.\n *\n * @module @kysera/rls/utils/type-utils\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { SelectQueryBuilder, Kysely, RawBuilder } from 'kysely'\nimport { sql } from 'kysely'\n\n/**\n * Type-safe wrapper for dynamic column references in WHERE clauses\n *\n * Kysely's type system requires compile-time known column names, but RLS policies\n * work with dynamic column names at runtime. This utility provides a type-safe\n * boundary for this conversion.\n *\n * Type safety is maintained through:\n * 1. Column names come from validated policy definitions (developer-controlled)\n * 2. Values are type-checked by policy condition functions\n * 3. Runtime validation during policy registration\n *\n * @param table - Table name (from validated policy schema)\n * @param column - Column name (from validated policy definition)\n * @returns Type-safe column reference for Kysely query builder\n */\nexport function createQualifiedColumn(table: string, column: string): string {\n return `${table}.${column}`\n}\n\n/**\n * Type-safe wrapper for applying WHERE conditions from RLS filters\n *\n * This function encapsulates the type boundary between runtime policy conditions\n * and Kysely's compile-time type system.\n *\n * @param qb - Query builder to modify\n * @param column - Qualified column name (table.column)\n * @param operator - Comparison operator\n * @param value - Value to compare against\n * @returns Modified query builder\n */\nexport function applyWhereCondition<DB, TB extends keyof DB & string, O>(\n qb: SelectQueryBuilder<DB, TB, O>,\n column: string,\n operator: 'is' | '=' | 'in',\n value: unknown\n): SelectQueryBuilder<DB, TB, O> {\n return qb.where(column as any, operator as any, value as any)\n}\n\n/**\n * Type-safe wrapper for raw SQL expressions\n *\n * @param expression - SQL expression (e.g., 'FALSE' for impossible conditions)\n * @returns Type-safe raw builder for WHERE clauses\n */\nexport function createRawCondition(expression: string): RawBuilder<boolean> {\n return sql`${sql.raw(expression)}`\n}\n\n/**\n * Type-safe wrapper for dynamic table queries (used in raw db queries)\n *\n * This is used by plugins to bypass RLS filtering when fetching existing rows\n * for mutation validation. The table name comes from repository configuration\n * and is validated during repository creation.\n *\n * @param db - Kysely database instance\n * @param table - Table name (from repository config)\n * @returns Query builder for the table\n */\nexport function selectFromDynamicTable<DB>(\n db: Kysely<DB>,\n table: string\n): SelectQueryBuilder<Record<string, unknown>, string, Record<string, unknown>> {\n return db.selectFrom(table as any).selectAll() as any\n}\n\n/**\n * Add WHERE clause for primary key equality.\n * Supports custom primary key column names.\n *\n * @param qb - Select query builder\n * @param id - Primary key value\n * @param primaryKeyColumn - Primary key column name (default: 'id')\n * @returns Query builder with ID filter\n */\nexport function whereIdEquals(\n qb: SelectQueryBuilder<any, any, any>,\n id: unknown,\n primaryKeyColumn = 'id'\n): SelectQueryBuilder<any, any, any> {\n return qb.where(primaryKeyColumn as any, '=', id as any)\n}\n\n/**\n * Type-safe wrapper for transforming query builders in plugin interceptors\n *\n * Used when plugins need to transform a generic query builder (QB) to a specific\n * type (e.g., SelectQueryBuilder) and back. This is necessary because the executor's\n * interceptQuery hook receives unconstrained QB types to preserve type inference.\n *\n * @param qb - Generic query builder from interceptor\n * @param operation - Operation type (for runtime validation)\n * @param transform - Transformation function\n * @returns Transformed query builder\n */\nexport function transformQueryBuilder<QB>(\n qb: QB,\n operation: string,\n transform: (\n qb: SelectQueryBuilder<Record<string, unknown>, string, Record<string, unknown>>\n ) => SelectQueryBuilder<Record<string, unknown>, string, Record<string, unknown>>\n): QB {\n if (operation !== 'select') {\n return qb\n }\n\n const transformed = transform(qb as any)\n return transformed as QB\n}\n\n/**\n * Type guard to check if an executor has a raw db instance\n *\n * @param executor - Kysely executor (may have __rawDb property)\n * @returns True if executor has __rawDb property\n */\nexport function hasRawDb<DB>(\n executor: Kysely<DB>\n): executor is Kysely<DB> & { __rawDb: Kysely<DB> } {\n return '__rawDb' in executor && (executor as any).__rawDb !== undefined\n}\n\n/**\n * Type-safe wrapper to get raw db from executor\n *\n * @param executor - Kysely executor with optional __rawDb\n * @returns Raw db instance or original executor\n */\nexport function getRawDbSafe<DB>(executor: Kysely<DB>): Kysely<DB> {\n if (hasRawDb(executor)) {\n return executor.__rawDb\n }\n return executor\n}\n","/**\n * SELECT Query Transformer\n * Applies filter policies to SELECT queries by adding WHERE conditions\n */\n\nimport type { SelectQueryBuilder } from 'kysely'\nimport type { PolicyRegistry } from '../policy/registry.js'\nimport type { PolicyEvaluationContext } from '../policy/types.js'\nimport type { RLSContext } from '../context/types.js'\nimport { rlsContext } from '../context/manager.js'\nimport { RLSError, RLSErrorCodes } from '../errors.js'\nimport {\n createQualifiedColumn,\n applyWhereCondition,\n createRawCondition\n} from '../utils/type-utils.js'\n\n/**\n * SELECT query transformer\n * Applies filter policies to SELECT queries by adding WHERE conditions\n */\nexport class SelectTransformer<DB = unknown> {\n constructor(private registry: PolicyRegistry<DB>) {}\n\n /**\n * Transform a SELECT query by applying filter policies\n *\n * @param qb - The query builder to transform\n * @param table - Table name being queried\n * @returns Transformed query builder with RLS filters applied\n *\n * @example\n * ```typescript\n * const transformer = new SelectTransformer(registry);\n * let query = db.selectFrom('posts').selectAll();\n * query = transformer.transform(query, 'posts');\n * // Query now includes WHERE conditions from RLS policies\n * ```\n */\n transform<TB extends keyof DB & string, O>(\n qb: SelectQueryBuilder<DB, TB, O>,\n table: string\n ): SelectQueryBuilder<DB, TB, O> {\n // Check for context\n const ctx = rlsContext.getContextOrNull()\n if (!ctx) {\n // SECURITY FIX (H-11): This should never happen as plugin.interceptQuery\n // now handles missing context. If we reach here, apply defensive WHERE FALSE\n // to prevent unfiltered queries from leaking through.\n // This is a defense-in-depth measure.\n return applyWhereCondition(\n qb,\n createRawCondition('FALSE') as unknown as string,\n '=',\n true\n ) as SelectQueryBuilder<DB, TB, O>\n }\n\n // Check if system user (bypass RLS)\n if (ctx.auth.isSystem) {\n return qb\n }\n\n // Check if user role should skip RLS\n const skipFor = this.registry.getSkipFor(table)\n if (skipFor.some(role => ctx.auth.roles.includes(role))) {\n return qb\n }\n\n // Get filter policies for this table\n const filters = this.registry.getFilters(table)\n if (filters.length === 0) {\n return qb\n }\n\n // Apply each filter as WHERE condition\n let result = qb\n for (const filter of filters) {\n const conditions = this.evaluateFilter(filter, ctx, table)\n result = this.applyConditions(result, conditions, table)\n }\n\n return result\n }\n\n /**\n * Evaluate a filter policy to get WHERE conditions\n *\n * @param filter - The filter policy to evaluate\n * @param ctx - RLS context\n * @param table - Table name\n * @returns WHERE clause conditions as key-value pairs\n */\n private evaluateFilter(\n filter: {\n name: string\n getConditions: (\n ctx: PolicyEvaluationContext\n ) => Record<string, unknown> | Promise<Record<string, unknown>>\n },\n ctx: RLSContext,\n table: string\n ): Record<string, unknown> {\n const evalCtx: PolicyEvaluationContext = {\n auth: ctx.auth,\n ...(ctx.meta !== undefined && { meta: ctx.meta as Record<string, unknown> })\n }\n\n const result = filter.getConditions(evalCtx)\n\n // Note: If async filters are needed, this method signature would need to change\n // For now, we assume synchronous filter evaluation\n if (result instanceof Promise) {\n throw new RLSError(\n `Async filter policies are not supported in SELECT transformers. ` +\n `Filter '${filter.name}' on table '${table}' returned a Promise. ` +\n `Use synchronous conditions for filter policies.`,\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n return result\n }\n\n /**\n * Apply filter conditions to query builder\n *\n * Uses type-safe wrappers from utils/type-utils.ts to encapsulate the boundary\n * between runtime policy conditions and Kysely's compile-time type system.\n *\n * Type safety is maintained through:\n * 1. Policy conditions are validated during schema registration\n * 2. Column names come from policy definitions (developer-controlled)\n * 3. Values are type-checked by the policy condition functions\n *\n * @param qb - Query builder to modify\n * @param conditions - WHERE clause conditions\n * @param table - Table name (for qualified column names)\n * @returns Modified query builder\n */\n private applyConditions<TB extends keyof DB & string, O>(\n qb: SelectQueryBuilder<DB, TB, O>,\n conditions: Record<string, unknown>,\n table: string\n ): SelectQueryBuilder<DB, TB, O> {\n let result = qb\n\n for (const [column, value] of Object.entries(conditions)) {\n // Use table-qualified column name to avoid ambiguity in joins\n const qualifiedColumn = createQualifiedColumn(table, column)\n\n if (value === null) {\n // NULL check\n result = applyWhereCondition(result, qualifiedColumn, 'is', null)\n } else if (value === undefined) {\n // Skip undefined values\n continue\n } else if (Array.isArray(value)) {\n if (value.length === 0) {\n // Empty array means no matches - add impossible condition using SQL FALSE\n // This ensures the query returns no rows without using magic strings\n // that could potentially match actual data\n result = applyWhereCondition(\n result,\n createRawCondition('FALSE') as unknown as string,\n '=',\n true\n )\n } else {\n // IN clause for array values\n result = applyWhereCondition(result, qualifiedColumn, 'in', value)\n }\n } else {\n // Equality check\n result = applyWhereCondition(result, qualifiedColumn, '=', value)\n }\n }\n\n return result\n }\n}\n","/**\n * Mutation Guard\n * Validates CREATE, UPDATE, DELETE operations against RLS policies\n */\n\nimport type { PolicyRegistry } from '../policy/registry.js'\nimport type { PolicyEvaluationContext, Operation } from '../policy/types.js'\nimport type { RLSContext } from '../context/types.js'\nimport { rlsContext } from '../context/manager.js'\nimport { RLSPolicyViolation, RLSPolicyEvaluationError } from '../errors.js'\n\n/**\n * Default chunk size for parallel row filtering\n */\nconst DEFAULT_CHUNK_SIZE = 100\n\n/**\n * Mutation guard\n * Validates mutations (CREATE, UPDATE, DELETE) against allow/deny/validate policies\n */\nexport class MutationGuard<DB = unknown> {\n constructor(private registry: PolicyRegistry<DB>) {}\n\n /**\n * Check if CREATE operation is allowed\n *\n * @param table - Table name\n * @param data - Data being inserted\n * @throws RLSPolicyViolation if access is denied\n *\n * @example\n * ```typescript\n * const guard = new MutationGuard(registry);\n * await guard.checkCreate('posts', { title: 'Hello', tenant_id: 1 });\n * ```\n */\n async checkCreate(table: string, data: Record<string, unknown>): Promise<void> {\n await this.checkMutation(table, 'create', undefined, data)\n }\n\n /**\n * Check if UPDATE operation is allowed\n *\n * @param table - Table name\n * @param existingRow - Current row data\n * @param data - Data being updated\n * @throws RLSPolicyViolation if access is denied\n *\n * @example\n * ```typescript\n * const guard = new MutationGuard(registry);\n * const existingPost = await db.selectFrom('posts').where('id', '=', 1).selectAll().executeTakeFirst();\n * await guard.checkUpdate('posts', existingPost, { title: 'Updated' });\n * ```\n */\n async checkUpdate(\n table: string,\n existingRow: Record<string, unknown>,\n data: Record<string, unknown>\n ): Promise<void> {\n await this.checkMutation(table, 'update', existingRow, data)\n }\n\n /**\n * Check if DELETE operation is allowed\n *\n * @param table - Table name\n * @param existingRow - Row to be deleted\n * @throws RLSPolicyViolation if access is denied\n *\n * @example\n * ```typescript\n * const guard = new MutationGuard(registry);\n * const existingPost = await db.selectFrom('posts').where('id', '=', 1).selectAll().executeTakeFirst();\n * await guard.checkDelete('posts', existingPost);\n * ```\n */\n async checkDelete(table: string, existingRow: Record<string, unknown>): Promise<void> {\n await this.checkMutation(table, 'delete', existingRow)\n }\n\n /**\n * Check if READ operation is allowed on a specific row\n *\n * @param table - Table name\n * @param row - Row to check access for\n * @returns true if access is allowed\n *\n * @example\n * ```typescript\n * const guard = new MutationGuard(registry);\n * const post = await db.selectFrom('posts').where('id', '=', 1).selectAll().executeTakeFirst();\n * const canRead = await guard.checkRead('posts', post);\n * ```\n */\n async checkRead(table: string, row: Record<string, unknown>): Promise<boolean> {\n try {\n await this.checkMutation(table, 'read', row)\n return true\n } catch (error) {\n // Both policy violations and evaluation errors result in denial\n if (error instanceof RLSPolicyViolation || error instanceof RLSPolicyEvaluationError) {\n return false\n }\n throw error\n }\n }\n\n /**\n * Generic check for any operation (helper for testing)\n *\n * @param operation - Operation type\n * @param table - Table name\n * @param row - Existing row (for UPDATE/DELETE/READ)\n * @param data - New data (for CREATE/UPDATE)\n * @returns true if access is allowed, false otherwise\n */\n async canMutate(\n operation: Operation,\n table: string,\n row?: Record<string, unknown>,\n data?: Record<string, unknown>\n ): Promise<boolean> {\n try {\n await this.checkMutation(table, operation, row, data)\n return true\n } catch (error) {\n // Both policy violations and evaluation errors result in denial\n if (error instanceof RLSPolicyViolation || error instanceof RLSPolicyEvaluationError) {\n return false\n }\n throw error\n }\n }\n\n /**\n * Validate mutation data (for validate policies)\n *\n * @param operation - Operation type\n * @param table - Table name\n * @param data - New data (for CREATE/UPDATE)\n * @param row - Existing row (for UPDATE)\n * @returns true if valid, false otherwise\n */\n async validateMutation(\n operation: Operation,\n table: string,\n data: Record<string, unknown>,\n row?: Record<string, unknown>\n ): Promise<boolean> {\n const ctx = rlsContext.getContextOrNull()\n if (!ctx) {\n return false\n }\n\n // System users bypass validation\n if (ctx.auth.isSystem) {\n return true\n }\n\n // Check skipFor roles\n const skipFor = this.registry.getSkipFor(table)\n if (skipFor.some(role => ctx.auth.roles.includes(role))) {\n return true\n }\n\n // Get validate policies for this operation\n const validates = this.registry.getValidates(table, operation)\n if (validates.length === 0) {\n return true\n }\n\n // Build evaluation context\n const evalCtx: PolicyEvaluationContext = {\n auth: ctx.auth,\n row: row,\n data: data,\n table: table,\n operation: operation,\n ...(ctx.meta !== undefined && { meta: ctx.meta as Record<string, unknown> })\n }\n\n // All validate policies must pass\n for (const validate of validates) {\n const result = await this.evaluatePolicy(validate.evaluate, evalCtx, validate.name)\n if (!result) {\n return false\n }\n }\n\n return true\n }\n\n /**\n * Check mutation against RLS policies\n *\n * @param table - Table name\n * @param operation - Operation type\n * @param row - Existing row (for UPDATE/DELETE/READ)\n * @param data - New data (for CREATE/UPDATE)\n * @throws RLSPolicyViolation if access is denied\n */\n private async checkMutation(\n table: string,\n operation: Operation,\n row?: Record<string, unknown>,\n data?: Record<string, unknown>\n ): Promise<void> {\n const ctx = rlsContext.getContextOrNull()\n if (!ctx) {\n throw new RLSPolicyViolation(operation, table, 'No RLS context available')\n }\n\n // System users bypass all checks\n if (ctx.auth.isSystem) {\n return\n }\n\n // Check if user role should skip RLS\n const skipFor = this.registry.getSkipFor(table)\n if (skipFor.some(role => ctx.auth.roles.includes(role))) {\n return\n }\n\n // Evaluate deny policies first (they override allows)\n const denies = this.registry.getDenies(table, operation)\n for (const deny of denies) {\n const evalCtx = this.createEvalContext(ctx, table, operation, row, data)\n const result = await this.evaluatePolicy(deny.evaluate, evalCtx, deny.name)\n\n if (result) {\n throw new RLSPolicyViolation(operation, table, `Denied by policy: ${deny.name}`)\n }\n }\n\n // Evaluate validate policies (for CREATE/UPDATE)\n if ((operation === 'create' || operation === 'update') && data) {\n const validates = this.registry.getValidates(table, operation)\n for (const validate of validates) {\n const evalCtx = this.createEvalContext(ctx, table, operation, row, data)\n const result = await this.evaluatePolicy(validate.evaluate, evalCtx, validate.name)\n\n if (!result) {\n throw new RLSPolicyViolation(operation, table, `Validation failed: ${validate.name}`)\n }\n }\n }\n\n // Evaluate allow policies\n const allows = this.registry.getAllows(table, operation)\n const defaultDeny = this.registry.hasDefaultDeny(table)\n\n if (defaultDeny && allows.length === 0) {\n throw new RLSPolicyViolation(operation, table, 'No allow policies defined (default deny)')\n }\n\n if (allows.length > 0) {\n // At least one allow policy must pass\n let allowed = false\n\n for (const allow of allows) {\n const evalCtx = this.createEvalContext(ctx, table, operation, row, data)\n const result = await this.evaluatePolicy(allow.evaluate, evalCtx, allow.name)\n\n if (result) {\n allowed = true\n break\n }\n }\n\n if (!allowed) {\n throw new RLSPolicyViolation(operation, table, 'No allow policies matched')\n }\n }\n }\n\n /**\n * Create policy evaluation context\n */\n private createEvalContext(\n ctx: RLSContext,\n table: string,\n operation: Operation,\n row?: Record<string, unknown>,\n data?: Record<string, unknown>\n ): PolicyEvaluationContext {\n return {\n auth: ctx.auth,\n row,\n data,\n table,\n operation,\n ...(ctx.meta !== undefined && { meta: ctx.meta as Record<string, unknown> })\n }\n }\n\n /**\n * Evaluate a policy condition\n *\n * @param condition - Policy condition function\n * @param evalCtx - Policy evaluation context\n * @param policyName - Name of the policy being evaluated (for error reporting)\n * @returns Boolean result of policy evaluation\n * @throws RLSPolicyEvaluationError if the policy throws an error\n */\n private async evaluatePolicy(\n condition: (ctx: PolicyEvaluationContext) => boolean | Promise<boolean>,\n evalCtx: PolicyEvaluationContext,\n policyName?: string\n ): Promise<boolean> {\n try {\n const result = condition(evalCtx)\n return result instanceof Promise ? await result : result\n } catch (error) {\n // Distinguish between policy evaluation errors and policy violations\n // RLSPolicyEvaluationError indicates a bug in the policy, not a legitimate denial\n const originalError = error instanceof Error ? error : undefined\n throw new RLSPolicyEvaluationError(\n evalCtx.operation ?? 'unknown',\n evalCtx.table ?? 'unknown',\n error instanceof Error ? error.message : 'Unknown error',\n policyName,\n originalError\n )\n }\n }\n\n /**\n * Filter rows based on read policies.\n * Uses parallel processing with chunking for performance.\n *\n * @param table - Table name\n * @param rows - Rows to filter\n * @param chunkSize - Number of rows to process in parallel (default: 100)\n * @returns Filtered array containing only accessible rows\n *\n * @example\n * ```typescript\n * const guard = new MutationGuard(registry);\n * const allPosts = await db.selectFrom('posts').selectAll().execute();\n * const accessiblePosts = await guard.filterRows('posts', allPosts);\n *\n * // With custom chunk size for large datasets\n * const accessiblePosts = await guard.filterRows('posts', allPosts, 50);\n * ```\n */\n async filterRows<T extends Record<string, unknown>>(\n table: string,\n rows: T[],\n chunkSize: number = DEFAULT_CHUNK_SIZE\n ): Promise<T[]> {\n if (rows.length === 0) return []\n\n const results: T[] = []\n\n // Process in chunks to avoid overwhelming the event loop\n for (let i = 0; i < rows.length; i += chunkSize) {\n const chunk = rows.slice(i, i + chunkSize)\n\n // Process chunk in parallel\n const chunkResults = await Promise.all(\n chunk.map(async (row) => {\n const allowed = await this.checkRead(table, row)\n return allowed ? row : null\n })\n )\n\n // Filter out nulls and add to results\n for (const row of chunkResults) {\n if (row !== null) {\n results.push(row)\n }\n }\n }\n\n return results\n }\n}\n","/**\n * Package version - injected at build time by tsup\n * Falls back to development version if not replaced\n * @internal\n */\nconst RAW_VERSION = '__VERSION__'\nexport const VERSION = RAW_VERSION.startsWith('__') ? '0.0.0-dev' : RAW_VERSION\n","/**\n * RLS Plugin for Kysera Repository\n *\n * Implements Row-Level Security as a Kysera plugin, providing:\n * - Automatic query filtering for SELECT operations\n * - Policy enforcement for CREATE, UPDATE, DELETE operations\n * - Repository method extensions for RLS-aware operations\n * - System context bypass for privileged operations\n *\n * @module @kysera/rls\n */\n\nimport type { Plugin, QueryBuilderContext, BaseRepositoryLike } from '@kysera/executor'\nimport { getRawDb, isRepositoryLike } from '@kysera/executor'\nimport type { Kysely } from 'kysely'\nimport { z } from 'zod'\nimport type { RLSSchema, Operation } from './policy/types.js'\nimport { PolicyRegistry } from './policy/registry.js'\nimport { SelectTransformer } from './transformer/select.js'\nimport { MutationGuard } from './transformer/mutation.js'\nimport { rlsContext } from './context/manager.js'\nimport { VERSION } from './version.js'\nimport { RLSContextError, RLSPolicyViolation, RLSError, RLSErrorCodes } from './errors.js'\nimport { silentLogger, type KyseraLogger } from '@kysera/core'\nimport {\n transformQueryBuilder,\n selectFromDynamicTable,\n whereIdEquals,\n hasRawDb as hasRawDbUtil,\n applyWhereCondition,\n createRawCondition\n} from './utils/type-utils.js'\n\n/**\n * RLS Plugin configuration options\n */\nexport interface RLSPluginOptions<DB = unknown> {\n /** RLS policy schema */\n schema: RLSSchema<DB>\n\n /**\n * Tables to exclude from RLS (always bypass policies)\n * @default []\n */\n excludeTables?: string[]\n\n /** Roles that bypass RLS entirely (e.g., ['admin', 'superuser']) */\n bypassRoles?: string[]\n\n /** Logger instance for RLS operations */\n logger?: KyseraLogger\n\n /**\n * Require RLS context for all operations (throws if missing)\n *\n * **Security**: Defaults to `true` for secure-by-default behavior.\n * When `true`, missing RLS context throws RLSContextError, preventing\n * unfiltered database access which could expose sensitive data.\n *\n * Only set to `false` if you explicitly want to allow queries without\n * RLS context (not recommended in production).\n *\n * @default true\n * @see allowUnfilteredQueries for explicit unfiltered query control\n */\n requireContext?: boolean\n\n /**\n * Allow unfiltered queries when RLS context is missing\n *\n * **SECURITY WARNING**: Setting this to `true` allows database queries\n * to execute without RLS filtering when context is missing. This can\n * expose sensitive data across tenant boundaries or user permissions.\n *\n * Only enable this if you:\n * 1. Understand the security implications\n * 2. Have other security controls in place\n * 3. Are running background jobs or system operations that don't have user context\n *\n * When both `requireContext: false` and `allowUnfilteredQueries: false`:\n * - Missing context logs a warning and returns empty results\n *\n * @default false (secure-by-default)\n */\n allowUnfilteredQueries?: boolean\n\n /** Enable audit logging of policy decisions */\n auditDecisions?: boolean\n\n /** Custom error handler for policy violations */\n onViolation?: (violation: RLSPolicyViolation) => void\n\n /**\n * Primary key column name for row lookups.\n * @default 'id'\n */\n primaryKeyColumn?: string\n}\n\n/**\n * Zod schema for RLSPluginOptions\n * Used for validation and configuration in the kysera-cli.\n * Note: 'schema' and 'onViolation' are not included as they are complex runtime objects.\n */\nexport const RLSPluginOptionsSchema = z.object({\n excludeTables: z.array(z.string()).optional(),\n bypassRoles: z.array(z.string()).optional(),\n requireContext: z.boolean().optional(),\n allowUnfilteredQueries: z.boolean().optional(),\n auditDecisions: z.boolean().optional(),\n primaryKeyColumn: z.string().optional()\n})\n\n/**\n * Base repository interface for type safety.\n * Type alias for BaseRepositoryLike from @kysera/executor with concrete DB type.\n * @internal\n */\ntype BaseRepository = BaseRepositoryLike<Record<string, unknown>>\n\n/**\n * Create RLS plugin for Kysera\n *\n * The RLS plugin provides declarative row-level security for your database operations.\n * It automatically filters SELECT queries and validates mutations (CREATE, UPDATE, DELETE)\n * against your policy schema.\n *\n * @example\n * ```typescript\n * import { rlsPlugin, defineRLSSchema, allow, filter } from '@kysera/rls';\n * import { createORM } from '@kysera/repository';\n *\n * // Define your RLS schema\n * const schema = defineRLSSchema<Database>({\n * resources: {\n * policies: [\n * // Filter reads by tenant\n * filter('read', ctx => ({ tenant_id: ctx.auth.tenantId })),\n * // Allow updates for resource owners\n * allow('update', ctx => ctx.auth.userId === ctx.row.owner_id),\n * // Validate creates belong to user's tenant\n * validate('create', ctx => ctx.data.tenant_id === ctx.auth.tenantId),\n * ],\n * },\n * });\n *\n * // Create repository with RLS plugin\n * const orm = await createORM(db, [\n * rlsPlugin({ schema }),\n * ]);\n *\n * // Use within RLS context\n * await rlsContext.runAsync(\n * {\n * auth: { userId: 1, tenantId: 100, roles: ['user'], isSystem: false },\n * timestamp: new Date(),\n * },\n * async () => {\n * // All queries automatically filtered by tenant_id\n * const resources = await orm.resources.findAll();\n * }\n * );\n * ```\n *\n * @param options - Plugin configuration options\n * @returns Kysera plugin instance\n */\nexport function rlsPlugin<DB>(options: RLSPluginOptions<DB>): Plugin {\n const {\n schema,\n excludeTables = [],\n bypassRoles = [],\n logger = silentLogger,\n requireContext = true, // SECURITY: Changed to true for secure-by-default (CRIT-2 fix)\n allowUnfilteredQueries = false, // SECURITY: Explicit opt-in for unfiltered queries\n auditDecisions = false,\n onViolation,\n primaryKeyColumn = 'id'\n } = options\n\n // Registry and transformers (initialized in onInit)\n let registry: PolicyRegistry<DB>\n let selectTransformer: SelectTransformer<DB>\n let mutationGuard: MutationGuard<DB>\n\n return {\n name: '@kysera/rls',\n version: VERSION,\n\n // Run after soft-delete (priority 0), before audit\n priority: 50,\n\n // No dependencies by default\n dependencies: [],\n\n /**\n * Initialize plugin - compile policies\n */\n onInit<TDB>(_executor: Kysely<TDB>): void {\n logger.info?.('[RLS] Initializing RLS plugin', {\n tables: Object.keys(schema).length,\n excludeTables: excludeTables.length,\n bypassRoles: bypassRoles.length\n })\n\n // Create and compile registry\n // Type assertion: The plugin is configured with a specific DB schema,\n // but onInit receives a generic TDB. We use the schema's DB type.\n registry = new PolicyRegistry<DB>(schema)\n registry.validate()\n\n // Create transformers\n selectTransformer = new SelectTransformer<DB>(registry)\n mutationGuard = new MutationGuard<DB>(registry)\n\n logger.info?.('[RLS] RLS plugin initialized successfully')\n },\n\n /**\n * Cleanup resources when executor is destroyed\n */\n async onDestroy(): Promise<void> {\n // Clear registry to free up memory\n registry.clear()\n logger.info?.('[RLS] RLS plugin destroyed, cleared policy registry')\n },\n\n /**\n * Intercept queries to apply RLS filtering\n *\n * This hook is called for every query builder operation. For SELECT queries,\n * it applies filter policies as WHERE conditions. For mutations, it marks\n * that RLS validation is required (performed in extendRepository).\n */\n interceptQuery<QB>(qb: QB, context: QueryBuilderContext): QB {\n const { operation, table, metadata } = context\n\n // Skip if table is excluded\n if (excludeTables.includes(table)) {\n logger.debug?.(`[RLS] Skipping RLS for excluded table: ${table}`)\n return qb\n }\n\n // Skip if explicitly disabled via metadata\n if (metadata['skipRLS'] === true) {\n logger.debug?.(`[RLS] Skipping RLS (explicit skip): ${table}`)\n return qb\n }\n\n // Check for context\n const ctx = rlsContext.getContextOrNull()\n\n if (!ctx) {\n // SECURITY FIX (CRIT-2): Secure-by-default behavior for missing context\n if (requireContext) {\n throw new RLSContextError(\n `RLS context required but not found for ${operation} on ${table}. ` +\n `This prevents unfiltered database access. ` +\n `Either provide RLS context or set 'requireContext: false' with 'allowUnfilteredQueries: true' if intentional.`\n )\n }\n\n if (!allowUnfilteredQueries) {\n // Log warning and return safe empty result\n logger.warn?.(\n `[RLS] Missing context for ${operation} on ${table}. ` +\n `Queries will return empty results for security. ` +\n `Set 'allowUnfilteredQueries: true' to allow unfiltered access (not recommended).`\n )\n // For SELECT, apply impossible condition to return no rows\n if (operation === 'select') {\n return transformQueryBuilder(qb, operation, selectQb => {\n // Apply WHERE FALSE to ensure no rows are returned\n return applyWhereCondition(\n selectQb,\n createRawCondition('FALSE') as unknown as string,\n '=',\n true\n ) as typeof selectQb\n })\n }\n // For mutations, we'll let them through but log warning\n // The extendRepository will handle mutation checks\n return qb\n }\n\n // allowUnfilteredQueries is true - allow but log warning\n logger.warn?.(\n `[RLS] No context for ${operation} on ${table}. ` +\n `Allowing unfiltered query due to 'allowUnfilteredQueries: true'. ` +\n `This may expose sensitive data.`\n )\n return qb\n }\n\n // Check if system user (bypass RLS)\n if (ctx.auth.isSystem) {\n logger.debug?.(`[RLS] Bypassing RLS (system user): ${table}`)\n return qb\n }\n\n // Check bypass roles\n if (bypassRoles.some(role => ctx.auth.roles.includes(role))) {\n logger.debug?.(`[RLS] Bypassing RLS (bypass role): ${table}`)\n return qb\n }\n\n // Apply SELECT filtering\n if (operation === 'select') {\n try {\n const transformed = transformQueryBuilder(\n qb,\n operation,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n selectQb => selectTransformer.transform(selectQb as any, table) as any\n )\n\n if (auditDecisions) {\n logger.info?.('[RLS] Filter applied', {\n table,\n operation,\n userId: ctx.auth.userId\n })\n }\n\n return transformed\n } catch (error) {\n logger.error?.('[RLS] Error applying filter', { table, error })\n throw error\n }\n }\n\n // For mutations, mark that RLS check is needed (done in extendRepository)\n if (operation === 'insert' || operation === 'update' || operation === 'delete') {\n metadata['__rlsRequired'] = true\n metadata['__rlsTable'] = table\n }\n\n return qb\n },\n\n /**\n * Extend repository with RLS-aware methods\n *\n * Wraps create, update, and delete methods to enforce RLS policies.\n * Also adds utility methods for bypassing RLS and checking access.\n */\n extendRepository<T extends object>(repo: T): T {\n // Use the shared type guard from @kysera/executor\n if (!isRepositoryLike(repo)) {\n return repo\n }\n\n const baseRepo = repo as unknown as BaseRepository\n\n const table = baseRepo.tableName\n\n // Skip excluded tables\n if (excludeTables.includes(table)) {\n logger.debug?.(`[RLS] Skipping repository extension for excluded table: ${table}`)\n return repo\n }\n\n // Skip if table not in schema\n if (!registry.hasTable(table)) {\n logger.debug?.(`[RLS] Table \"${table}\" not in RLS schema, skipping`)\n return repo\n }\n\n logger.debug?.(`[RLS] Extending repository for table: ${table}`)\n\n // Store original methods\n const originalCreate = baseRepo.create?.bind(baseRepo)\n const originalUpdate = baseRepo.update?.bind(baseRepo)\n const originalDelete = baseRepo.delete?.bind(baseRepo)\n const originalFindById = baseRepo.findById?.bind(baseRepo)\n\n // Get raw db for internal queries that need to bypass RLS\n // If executor doesn't have __rawDb (e.g., in tests), we'll use originalFindById\n const rawDb = getRawDb(baseRepo.executor)\n const hasRawDbInstance = hasRawDbUtil(baseRepo.executor)\n\n const extendedRepo = {\n ...baseRepo,\n\n /**\n * Wrapped create with RLS check\n */\n async create(data: unknown): Promise<unknown> {\n if (!originalCreate) {\n throw new RLSError(\n 'Repository does not support create operation',\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n const ctx = rlsContext.getContextOrNull()\n\n // Check RLS if context exists and not system/bypass\n if (\n ctx &&\n !ctx.auth.isSystem &&\n !bypassRoles.some(role => ctx.auth.roles.includes(role))\n ) {\n try {\n await mutationGuard.checkCreate(table, data as Record<string, unknown>)\n\n if (auditDecisions) {\n logger.info?.('[RLS] Create allowed', { table, userId: ctx.auth.userId })\n }\n } catch (error) {\n if (error instanceof RLSPolicyViolation) {\n onViolation?.(error)\n if (auditDecisions) {\n logger.warn?.('[RLS] Create denied', {\n table,\n userId: ctx.auth.userId,\n reason: error.reason\n })\n }\n }\n throw error\n }\n }\n\n return await originalCreate(data)\n },\n\n /**\n * Wrapped update with RLS check\n */\n async update(id: unknown, data: unknown): Promise<unknown> {\n if (!originalUpdate) {\n throw new RLSError(\n 'Repository does not support update operation',\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n const ctx = rlsContext.getContextOrNull()\n\n if (\n ctx &&\n !ctx.auth.isSystem &&\n !bypassRoles.some(role => ctx.auth.roles.includes(role))\n ) {\n // Fetch existing row for policy evaluation\n // Use raw db if available to bypass RLS filtering and prevent self-interception\n let existingRow: unknown\n\n if (hasRawDbInstance) {\n // Use raw db to bypass RLS filtering\n const query = selectFromDynamicTable(rawDb, table)\n existingRow = await whereIdEquals(query, id, primaryKeyColumn).executeTakeFirst()\n } else if (originalFindById) {\n // Fallback to originalFindById for tests/mocks\n existingRow = await originalFindById(id)\n } else {\n throw new RLSError(\n 'Repository does not support update operation',\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n if (!existingRow) {\n // Let the original method handle not found\n return await originalUpdate(id, data)\n }\n\n try {\n await mutationGuard.checkUpdate(\n table,\n existingRow as Record<string, unknown>,\n data as Record<string, unknown>\n )\n\n if (auditDecisions) {\n logger.info?.('[RLS] Update allowed', { table, id, userId: ctx.auth.userId })\n }\n } catch (error) {\n if (error instanceof RLSPolicyViolation) {\n onViolation?.(error)\n if (auditDecisions) {\n logger.warn?.('[RLS] Update denied', {\n table,\n id,\n userId: ctx.auth.userId,\n reason: error.reason\n })\n }\n }\n throw error\n }\n }\n\n return await originalUpdate(id, data)\n },\n\n /**\n * Wrapped delete with RLS check\n */\n async delete(id: unknown): Promise<unknown> {\n if (!originalDelete) {\n throw new RLSError(\n 'Repository does not support delete operation',\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n const ctx = rlsContext.getContextOrNull()\n\n if (\n ctx &&\n !ctx.auth.isSystem &&\n !bypassRoles.some(role => ctx.auth.roles.includes(role))\n ) {\n // Fetch existing row for policy evaluation\n // Use raw db if available to bypass RLS filtering and prevent self-interception\n let existingRow: unknown\n\n if (hasRawDbInstance) {\n // Use raw db to bypass RLS filtering\n const query = selectFromDynamicTable(rawDb, table)\n existingRow = await whereIdEquals(query, id, primaryKeyColumn).executeTakeFirst()\n } else if (originalFindById) {\n // Fallback to originalFindById for tests/mocks\n existingRow = await originalFindById(id)\n } else {\n throw new RLSError(\n 'Repository does not support delete operation',\n RLSErrorCodes.RLS_POLICY_INVALID\n )\n }\n\n if (!existingRow) {\n // Let the original method handle not found\n return await originalDelete(id)\n }\n\n try {\n await mutationGuard.checkDelete(table, existingRow as Record<string, unknown>)\n\n if (auditDecisions) {\n logger.info?.('[RLS] Delete allowed', { table, id, userId: ctx.auth.userId })\n }\n } catch (error) {\n if (error instanceof RLSPolicyViolation) {\n onViolation?.(error)\n if (auditDecisions) {\n logger.warn?.('[RLS] Delete denied', {\n table,\n id,\n userId: ctx.auth.userId,\n reason: error.reason\n })\n }\n }\n throw error\n }\n }\n\n return await originalDelete(id)\n },\n\n /**\n * Bypass RLS for specific operation\n * Requires existing context\n *\n * @example\n * ```typescript\n * // Perform operation as system user\n * const result = await repo.withoutRLS(async () => {\n * return repo.findAll(); // No RLS filtering\n * });\n * ```\n */\n async withoutRLS<R>(fn: () => Promise<R>): Promise<R> {\n return await rlsContext.asSystemAsync(fn)\n },\n\n /**\n * Check if current user can perform operation on a row\n *\n * @example\n * ```typescript\n * const post = await repo.findById(1);\n * const canUpdate = await repo.canAccess('update', post);\n * if (canUpdate) {\n * await repo.update(1, { title: 'New title' });\n * }\n * ```\n */\n async canAccess(operation: Operation, row: Record<string, unknown>): Promise<boolean> {\n const ctx = rlsContext.getContextOrNull()\n if (!ctx) return false\n if (ctx.auth.isSystem) return true\n if (bypassRoles.some(role => ctx.auth.roles.includes(role))) return true\n\n try {\n switch (operation) {\n case 'read':\n return await mutationGuard.checkRead(table, row)\n case 'create':\n await mutationGuard.checkCreate(table, row)\n return true\n case 'update':\n await mutationGuard.checkUpdate(table, row, {})\n return true\n case 'delete':\n await mutationGuard.checkDelete(table, row)\n return true\n default:\n return false\n }\n } catch (error) {\n logger.debug?.('[RLS] Access check failed', {\n table,\n operation,\n error: error instanceof Error ? error.message : String(error)\n })\n return false\n }\n }\n }\n\n return extendedRepo as T\n }\n }\n}\n","/**\n * Utility helper functions for RLS\n */\n\nimport type { RLSContext, PolicyEvaluationContext, Operation } from '../policy/types.js'\n\n/**\n * Create a policy evaluation context from RLS context\n */\nexport function createEvaluationContext<TRow = unknown, TData = unknown>(\n rlsCtx: RLSContext,\n options?: {\n row?: TRow\n data?: TData\n }\n): PolicyEvaluationContext<unknown, TRow, TData> {\n const ctx: PolicyEvaluationContext<unknown, TRow, TData> = {\n auth: rlsCtx.auth\n }\n\n if (options?.row !== undefined) {\n ctx.row = options.row\n }\n\n if (options?.data !== undefined) {\n ctx.data = options.data\n }\n\n if (rlsCtx.request !== undefined) {\n ctx.request = rlsCtx.request\n }\n\n if (rlsCtx.meta !== undefined) {\n ctx.meta = rlsCtx.meta as Record<string, unknown>\n }\n\n return ctx\n}\n\n/**\n * Check if a condition function is async\n *\n * NOTE: This function checks both constructor.name (for native async functions)\n * and return type (for transpiled code that returns Promise).\n * Transpilers often convert async functions to regular functions that return Promise.\n */\nexport function isAsyncFunction(fn: unknown): fn is (...args: unknown[]) => Promise<unknown> {\n if (!(fn instanceof Function)) {\n return false\n }\n\n // Check constructor name for native async functions\n if (fn.constructor.name === 'AsyncFunction') {\n return true\n }\n\n // For transpiled code: call the function with empty args and check if it returns a Promise\n // This is safe because policy conditions should be pure functions\n try {\n const result = (fn as Function)()\n return result instanceof Promise\n } catch {\n // If calling with no args throws, assume it's not async\n // (async functions that require args should be wrapped in the policy definition)\n return false\n }\n}\n\n/**\n * Safely evaluate a policy condition\n */\nexport async function safeEvaluate<T>(fn: () => T | Promise<T>, defaultValue: T): Promise<T> {\n try {\n const result = fn()\n if (result instanceof Promise) {\n return await result\n }\n return result\n } catch (_error) {\n // Expected failure during policy evaluation - return default value\n // Logger not available in this utility function, error is handled gracefully\n return defaultValue\n }\n}\n\n/**\n * Deep merge two objects\n */\nexport function deepMerge<T extends Record<string, unknown>>(target: T, source: Partial<T>): T {\n const result = { ...target }\n\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceValue = source[key]\n const targetValue = result[key]\n\n if (\n sourceValue !== undefined &&\n typeof sourceValue === 'object' &&\n sourceValue !== null &&\n !Array.isArray(sourceValue) &&\n typeof targetValue === 'object' &&\n targetValue !== null &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>\n ) as T[keyof T]\n } else if (sourceValue !== undefined) {\n result[key] = sourceValue as T[keyof T]\n }\n }\n\n return result\n}\n\n/**\n * Create a simple hash for cache keys\n */\nexport function hashString(str: string): string {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32bit integer\n }\n return hash.toString(36)\n}\n\n/**\n * Normalize operations to array format\n */\nexport function normalizeOperations(operation: Operation | Operation[]): Operation[] {\n if (Array.isArray(operation)) {\n if (operation.includes('all')) {\n return ['read', 'create', 'update', 'delete']\n }\n return operation\n }\n\n if (operation === 'all') {\n return ['read', 'create', 'update', 'delete']\n }\n\n return [operation]\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kysera/rls",
3
- "version": "0.7.4",
3
+ "version": "0.8.0",
4
4
  "description": "Row-Level Security plugin for Kysely - declarative policies, query transformation, native RLS support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -21,8 +21,8 @@
21
21
  ],
22
22
  "peerDependencies": {
23
23
  "kysely": ">=0.28.8",
24
- "@kysera/executor": "0.7.4",
25
- "@kysera/repository": "0.7.4"
24
+ "@kysera/executor": "0.8.0",
25
+ "@kysera/repository": "0.8.0"
26
26
  },
27
27
  "peerDependenciesMeta": {
28
28
  "@kysera/executor": {
@@ -33,7 +33,7 @@
33
33
  }
34
34
  },
35
35
  "dependencies": {
36
- "@kysera/core": "0.7.4"
36
+ "@kysera/core": "0.8.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/better-sqlite3": "^7.6.13",
@@ -47,8 +47,8 @@
47
47
  "tsup": "^8.5.1",
48
48
  "typescript": "^5.9.3",
49
49
  "vitest": "^4.0.16",
50
- "@kysera/executor": "0.7.4",
51
- "@kysera/repository": "0.7.4"
50
+ "@kysera/executor": "0.8.0",
51
+ "@kysera/repository": "0.8.0"
52
52
  },
53
53
  "keywords": [
54
54
  "kysely",
package/src/plugin.ts CHANGED
@@ -40,17 +40,10 @@ export interface RLSPluginOptions<DB = unknown> {
40
40
 
41
41
  /**
42
42
  * Tables to exclude from RLS (always bypass policies)
43
- * Replaces the deprecated `skipTables` option for consistency with other plugins.
44
43
  * @default []
45
44
  */
46
45
  excludeTables?: string[]
47
46
 
48
- /**
49
- * @deprecated Use `excludeTables` instead for consistency with other Kysera plugins
50
- * @default []
51
- */
52
- skipTables?: string[]
53
-
54
47
  /** Roles that bypass RLS entirely (e.g., ['admin', 'superuser']) */
55
48
  bypassRoles?: string[]
56
49
 
@@ -111,7 +104,6 @@ export interface RLSPluginOptions<DB = unknown> {
111
104
  */
112
105
  export const RLSPluginOptionsSchema = z.object({
113
106
  excludeTables: z.array(z.string()).optional(),
114
- skipTables: z.array(z.string()).optional(), // deprecated but kept for backward compatibility
115
107
  bypassRoles: z.array(z.string()).optional(),
116
108
  requireContext: z.boolean().optional(),
117
109
  allowUnfilteredQueries: z.boolean().optional(),
@@ -176,8 +168,7 @@ type BaseRepository = BaseRepositoryLike<Record<string, unknown>>
176
168
  export function rlsPlugin<DB>(options: RLSPluginOptions<DB>): Plugin {
177
169
  const {
178
170
  schema,
179
- excludeTables: excludeTablesOption,
180
- skipTables: skipTablesOption,
171
+ excludeTables = [],
181
172
  bypassRoles = [],
182
173
  logger = silentLogger,
183
174
  requireContext = true, // SECURITY: Changed to true for secure-by-default (CRIT-2 fix)
@@ -187,17 +178,6 @@ export function rlsPlugin<DB>(options: RLSPluginOptions<DB>): Plugin {
187
178
  primaryKeyColumn = 'id'
188
179
  } = options
189
180
 
190
- // Backward compatibility: support both excludeTables and skipTables
191
- // excludeTables takes precedence if both are provided
192
- const excludeTables = excludeTablesOption ?? skipTablesOption ?? []
193
-
194
- // Warn if deprecated skipTables is used
195
- if (skipTablesOption !== undefined && excludeTablesOption === undefined) {
196
- logger.warn?.(
197
- '[RLS] The "skipTables" option is deprecated. Use "excludeTables" instead for consistency with other Kysera plugins.'
198
- )
199
- }
200
-
201
181
  // Registry and transformers (initialized in onInit)
202
182
  let registry: PolicyRegistry<DB>
203
183
  let selectTransformer: SelectTransformer<DB>