// src/lib/permission-catalog.ts
import { getPermissionEntries } from "@mesob/common";

// src/db/schema.ts
import { pgSchema, index, uniqueIndex, foreignKey, unique, pgPolicy, check, uuid, varchar, timestamp, text, boolean, smallint, jsonb, inet } from "drizzle-orm/pg-core";
import { sql } from "drizzle-orm";
var iam = pgSchema("iam");
var usersInIam = iam.table("users", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  createdAt: timestamp("created_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  fullName: text("full_name").notNull(),
  image: text(),
  phone: text(),
  email: text(),
  handle: text().notNull(),
  emailVerified: boolean("email_verified").default(false).notNull(),
  phoneVerified: boolean("phone_verified").default(false).notNull(),
  bannedUntil: timestamp("banned_until", { withTimezone: true, mode: "string" }),
  lastSignInAt: timestamp("last_sign_in_at", { withTimezone: true, mode: "string" }),
  loginAttempt: smallint("login_attempt").default(0).notNull(),
  userType: text("user_type").array().default(["RAY"]).notNull(),
  normalizedEmail: text("normalized_email")
}, (table) => [
  index("idx_users_auth_lookup").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.email.asc().nullsLast().op("text_ops"), table.id.asc().nullsLast().op("timestamptz_ops"), table.emailVerified.asc().nullsLast().op("bool_ops"), table.bannedUntil.asc().nullsLast().op("timestamptz_ops")).where(sql`(email IS NOT NULL)`),
  index("idx_users_email_lookup").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.email.asc().nullsLast().op("text_ops")).where(sql`(email IS NOT NULL)`),
  index("idx_users_handle_lookup").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.handle.asc().nullsLast().op("text_ops")),
  index("idx_users_phone_lookup").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.phone.asc().nullsLast().op("text_ops")).where(sql`(phone IS NOT NULL)`),
  index("idx_users_tenant_email_unique").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.email.asc().nullsLast().op("text_ops")).where(sql`(email IS NOT NULL)`),
  index("idx_users_tenant_is_admin").using("btree", table.tenantId.asc().nullsLast().op("text_ops")).where(sql`(user_type @> ARRAY['admin'::text])`),
  index("idx_users_tenant_is_candidate").using("btree", table.tenantId.asc().nullsLast().op("text_ops")).where(sql`(user_type @> ARRAY['candidate'::text])`),
  index("idx_users_tenant_is_employee").using("btree", table.tenantId.asc().nullsLast().op("text_ops")).where(sql`(user_type @> ARRAY['employee'::text])`),
  index("idx_users_user_types_gin").using("gin", table.userType.asc().nullsLast().op("array_ops")),
  uniqueIndex("users_tenant_lower_handle_idx").using("btree", sql`tenant_id`, sql`lower(handle)`),
  uniqueIndex("users_tenant_normalized_email_idx").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.normalizedEmail.asc().nullsLast().op("text_ops")),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "users_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  unique("users_tenant_phone_key").on(table.tenantId, table.phone),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` }),
  check("users_contact_required_check", sql`(email IS NOT NULL) OR (phone IS NOT NULL)`),
  check("users_login_attempt_nonnegative_check", sql`login_attempt >= 0`),
  check("users_user_type_check", sql`user_type <@ ARRAY['candidate'::text, 'employee'::text, 'admin'::text, 'talent'::text]`)
]);
var tenantsInIam = iam.table("tenants", {
  id: varchar({ length: 30 }).primaryKey().notNull(),
  createdAt: timestamp("created_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  name: jsonb().notNull(),
  description: jsonb(),
  theme: jsonb(),
  supportedLanguages: jsonb("supported_languages"),
  defaultLanguage: text("default_language"),
  supportedCurrency: jsonb("supported_currency"),
  defaultCurrency: text("default_currency"),
  timezone: text(),
  isActive: boolean("is_active").default(true).notNull(),
  locale: jsonb(),
  settings: jsonb(),
  seo: jsonb()
}, (table) => [
  index("tenants_is_active_idx").using("btree", table.isActive.asc().nullsLast().op("bool_ops"))
]);
var verificationsInIam = iam.table("verifications", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  createdAt: timestamp("created_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  userId: uuid("user_id").notNull(),
  code: text().notNull(),
  expiresAt: timestamp("expires_at", { withTimezone: true, mode: "string" }).notNull(),
  type: text(),
  attempt: smallint().default(0),
  to: text()
}, (table) => [
  index("verifications_expires_at_idx").using("btree", table.expiresAt.asc().nullsLast().op("timestamptz_ops")),
  index("verifications_lookup_idx").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.userId.asc().nullsLast().op("text_ops"), table.type.asc().nullsLast().op("uuid_ops"), table.to.asc().nullsLast().op("text_ops"), table.code.asc().nullsLast().op("text_ops")),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "verifications_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  foreignKey({
    columns: [table.userId],
    foreignColumns: [usersInIam.id],
    name: "verifications_user_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` }),
  check("verifications_attempt_nonnegative_check", sql`attempt >= 0`),
  check("verifications_expires_after_created_check", sql`expires_at > created_at`)
]);
var sessionsInIam = iam.table("sessions", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  createdAt: timestamp("created_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  userId: uuid("user_id").notNull(),
  expiresAt: timestamp("expires_at", { withTimezone: true, mode: "string" }).notNull(),
  userAgent: text("user_agent"),
  ip: inet(),
  meta: jsonb(),
  token: text().notNull(),
  rotatedAt: timestamp("rotated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`)
}, (table) => [
  index("sessions_expires_at_idx").using("btree", table.expiresAt.asc().nullsLast().op("timestamptz_ops")),
  index("sessions_tenant_user_idx").using("btree", table.tenantId.asc().nullsLast().op("uuid_ops"), table.userId.asc().nullsLast().op("text_ops")),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "sessions_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  foreignKey({
    columns: [table.userId],
    foreignColumns: [usersInIam.id],
    name: "sessions_user_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  unique("sessions_token_key").on(table.token),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` }),
  check("sessions_expires_after_created_check", sql`expires_at > created_at`)
]);
var accountChangesInIam = iam.table("account_changes", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  userId: uuid("user_id").notNull(),
  createdAt: timestamp("created_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  changeType: text("change_type").notNull(),
  oldEmail: varchar("old_email"),
  newEmail: varchar("new_email"),
  oldPhone: text("old_phone"),
  newPhone: text("new_phone"),
  status: varchar().notNull(),
  expiresAt: timestamp("expires_at", { withTimezone: true, mode: "string" }).notNull(),
  confirmedAt: timestamp("confirmed_at", { withTimezone: true, mode: "string" }),
  cancelledAt: timestamp("cancelled_at", { withTimezone: true, mode: "string" }),
  reason: text()
}, (table) => [
  index("account_changes_expires_at_idx").using("btree", table.expiresAt.asc().nullsLast().op("timestamptz_ops")),
  index("account_changes_tenant_user_status_idx").using("btree", table.tenantId.asc().nullsLast().op("uuid_ops"), table.userId.asc().nullsLast().op("text_ops"), table.status.asc().nullsLast().op("uuid_ops")),
  index("idx_account_changes_expired").using("btree", table.expiresAt.asc().nullsLast().op("text_ops"), table.status.asc().nullsLast().op("text_ops")).where(sql`((status)::text = 'pending'::text)`),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "account_changes_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  foreignKey({
    columns: [table.userId],
    foreignColumns: [usersInIam.id],
    name: "account_changes_user_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` }),
  check("account_changes_change_type_check", sql`((change_type = 'EMAIL'::text) AND (old_email IS NOT NULL) AND (new_email IS NOT NULL) AND (old_phone IS NULL) AND (new_phone IS NULL)) OR ((change_type = 'PHONE'::text) AND (old_phone IS NOT NULL) AND (new_phone IS NOT NULL) AND (old_email IS NULL) AND (new_email IS NULL))`),
  check("account_changes_expires_after_created_check", sql`expires_at > created_at`),
  check("account_changes_status_check", sql`(status)::text = ANY (ARRAY[('PENDING'::character varying)::text, ('APPLIED'::character varying)::text, ('CANCELLED'::character varying)::text, ('EXPIRED'::character varying)::text])`)
]);
var rolePermissionsInIam = iam.table("role_permissions", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  permissionId: text("permission_id").notNull(),
  roleId: uuid("role_id").notNull()
}, (table) => [
  index("idx_role_permissions_permission_id").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.permissionId.asc().nullsLast().op("text_ops")),
  foreignKey({
    columns: [table.permissionId],
    foreignColumns: [permissionsInIam.id],
    name: "role_permissions_permission_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "role_permissions_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  foreignKey({
    columns: [table.tenantId, table.roleId],
    foreignColumns: [rolesInIam.tenantId, rolesInIam.id],
    name: "role_permissions_tenant_role_fkey"
  }).onDelete("cascade"),
  unique("role_permissions_tenant_role_permission_unique").on(table.tenantId, table.permissionId, table.roleId),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` })
]);
var permissionsInIam = iam.table("permissions", {
  id: text().primaryKey().notNull(),
  description: jsonb().notNull(),
  activity: text().notNull(),
  application: text().notNull(),
  feature: text().notNull()
}, (table) => [
  unique("permissions_activity_application_feature_key").on(table.activity, table.application, table.feature)
]);
var accountsInIam = iam.table("accounts", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  userId: uuid("user_id").notNull(),
  provider: text().notNull(),
  providerAccountId: text("provider_account_id").notNull(),
  password: text(),
  passwordLastChangedAt: timestamp("password_last_changed_at", { withTimezone: true, mode: "string" }),
  idToken: text("id_token"),
  accessToken: text("access_token"),
  accessTokenExpiresAt: timestamp("access_token_expires_at", { withTimezone: true, mode: "string" }),
  refreshToken: text("refresh_token"),
  refreshTokenExpiresAt: timestamp("refresh_token_expires_at", { withTimezone: true, mode: "string" }),
  scope: text(),
  expiresAt: timestamp("expires_at", { withTimezone: true, mode: "string" }),
  meta: jsonb()
}, (table) => [
  index("idx_accounts_provider_lookup").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.provider.asc().nullsLast().op("text_ops"), table.providerAccountId.asc().nullsLast().op("text_ops")),
  index("idx_accounts_user_id").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.userId.asc().nullsLast().op("text_ops")),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "accounts_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  foreignKey({
    columns: [table.userId],
    foreignColumns: [usersInIam.id],
    name: "accounts_user_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  unique("accounts_tenant_provider_account_unique").on(table.tenantId, table.provider, table.providerAccountId),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` })
]);
var scopesInIam = iam.table("scopes", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  createdAt: timestamp("created_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  code: text().notNull(),
  name: text().notNull(),
  description: text(),
  meta: jsonb()
}, (table) => [
  index("scopes_tenant_id_idx").using("btree", table.tenantId.asc().nullsLast().op("text_ops")),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "scopes_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  unique("scopes_tenant_id_id_key").on(table.id, table.tenantId),
  unique("scopes_tenant_code_key").on(table.tenantId, table.code),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` })
]);
var rolesInIam = iam.table("roles", {
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  createdAt: timestamp("created_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  name: jsonb().notNull(),
  description: jsonb().notNull(),
  code: text().notNull(),
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  isSystem: boolean("is_system").default(false).notNull(),
  isEditable: boolean("is_editable").default(true).notNull(),
  isDeletable: boolean("is_deletable").default(true).notNull()
}, (table) => [
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "roles_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  unique("roles_tenant_code_unique").on(table.tenantId, table.code),
  unique("roles_tenant_id_unique").on(table.tenantId, table.id),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` })
]);
var accessTokensInIam = iam.table("access_tokens", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  userId: uuid("user_id").notNull(),
  createdAt: timestamp("created_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  name: text().notNull(),
  description: text(),
  expiresAt: timestamp("expires_at", { withTimezone: true, mode: "string" }),
  lastUsedAt: timestamp("last_used_at", { withTimezone: true, mode: "string" }),
  lastUsedIps: jsonb("last_used_ips").default([]).notNull(),
  status: text().default("active").notNull(),
  secretHash: text("secret_hash").notNull(),
  meta: jsonb()
}, (table) => [
  index("access_tokens_status_idx").using("btree", table.status.asc().nullsLast().op("text_ops")).where(sql`(status = 'active'::text)`),
  index("access_tokens_tenant_user_idx").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.userId.asc().nullsLast().op("text_ops")),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "access_tokens_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  foreignKey({
    columns: [table.userId],
    foreignColumns: [usersInIam.id],
    name: "access_tokens_user_id_fkey"
  }).onDelete("cascade"),
  unique("access_tokens_tenant_id_id_key").on(table.id, table.tenantId),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` }),
  check("access_tokens_expires_after_created_check", sql`(expires_at IS NULL) OR (expires_at > created_at)`),
  check("access_tokens_status_check", sql`status = ANY (ARRAY['active'::text, 'revoked'::text])`)
]);
var userRolesInIam = iam.table("user_roles", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  userId: uuid("user_id").notNull(),
  roleId: uuid("role_id").notNull()
}, (table) => [
  index("idx_user_roles_tenant_user").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.userId.asc().nullsLast().op("uuid_ops")),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "user_roles_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  foreignKey({
    columns: [table.tenantId, table.roleId],
    foreignColumns: [rolesInIam.tenantId, rolesInIam.id],
    name: "user_roles_tenant_role_fkey"
  }).onDelete("cascade"),
  foreignKey({
    columns: [table.userId],
    foreignColumns: [usersInIam.id],
    name: "user_roles_user_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  unique("user_roles_tenant_user_role_unique").on(table.tenantId, table.userId, table.roleId),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` })
]);
var accessTokenScopesInIam = iam.table("access_token_scopes", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  accessTokenId: uuid("access_token_id").notNull(),
  scopeId: uuid("scope_id").notNull()
}, (table) => [
  index("access_token_scopes_scope_idx").using("btree", table.scopeId.asc().nullsLast().op("uuid_ops")),
  index("access_token_scopes_tenant_idx").using("btree", table.tenantId.asc().nullsLast().op("text_ops")),
  index("access_token_scopes_token_idx").using("btree", table.accessTokenId.asc().nullsLast().op("uuid_ops")),
  foreignKey({
    columns: [table.tenantId, table.accessTokenId],
    foreignColumns: [accessTokensInIam.id, accessTokensInIam.tenantId],
    name: "access_token_scopes_access_token_fkey"
  }).onDelete("cascade"),
  foreignKey({
    columns: [table.tenantId, table.scopeId],
    foreignColumns: [scopesInIam.id, scopesInIam.tenantId],
    name: "access_token_scopes_scope_fkey"
  }).onDelete("restrict"),
  unique("access_token_scopes_access_token_scope_key").on(table.accessTokenId, table.scopeId),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` })
]);
var domainsInIam = iam.table("domains", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  domain: text().notNull(),
  status: text().default("pending").notNull(),
  meta: jsonb(),
  isPrimary: boolean("is_primary").default(false).notNull(),
  createdAt: timestamp("created_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  app: text()
}, (table) => [
  uniqueIndex("domains_active_per_tenant_app_idx").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.app.asc().nullsLast().op("text_ops")).where(sql`(status = 'ACTIVE'::text)`),
  uniqueIndex("domains_domain_tenant_app_unique_idx").using("btree", sql`lower(domain)`, sql`tenant_id`, sql`COALESCE(app, ''::text)`).where(sql`(app IS NOT NULL)`),
  index("domains_tenant_status_idx").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.status.asc().nullsLast().op("text_ops")),
  index("idx_domains_tenant_domain_status").using("btree", table.tenantId.asc().nullsLast().op("text_ops"), table.domain.asc().nullsLast().op("text_ops"), table.status.asc().nullsLast().op("text_ops")),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "domains_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` }),
  check("domains_domain_format_check", sql`domain ~ '^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)+$'::text`),
  check("domains_status_check", sql`status = ANY (ARRAY['PENDING'::text, 'ACTIVE'::text, 'DISABLED'::text, 'DELETED'::text])`)
]);
var featuresInIam = iam.table("features", {
  id: uuid().default(sql`uuid_generate_v7()`).primaryKey().notNull(),
  tenantId: varchar("tenant_id", { length: 30 }).notNull(),
  featureCode: text("feature_code").notNull(),
  isEnabled: boolean("is_enabled").default(true).notNull(),
  isOverriddenByAdmin: boolean("is_overridden_by_admin").default(false).notNull(),
  isOverriddenByTenant: boolean("is_overridden_by_tenant").default(false).notNull(),
  createdAt: timestamp("created_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
  meta: jsonb()
}, (table) => [
  index("features_feature_code_idx").using("btree", table.featureCode.asc().nullsLast().op("text_ops")),
  index("features_tenant_id_idx").using("btree", table.tenantId.asc().nullsLast().op("text_ops")),
  foreignKey({
    columns: [table.tenantId],
    foreignColumns: [tenantsInIam.id],
    name: "features_tenant_id_fkey"
  }).onUpdate("cascade").onDelete("cascade"),
  unique("features_tenant_id_feature_code_key").on(table.tenantId, table.featureCode),
  pgPolicy("tenant_isolation", { as: "permissive", for: "all", to: ["public"], using: sql`((tenant_id)::text = (iam.current_tenant_id())::text)`, withCheck: sql`((tenant_id)::text = (iam.current_tenant_id())::text)` })
]);

// src/lib/permission-catalog.ts
var collator = new Intl.Collator(void 0, {
  numeric: true,
  sensitivity: "base"
});
var sortValueMap = {
  id: (permission) => permission.id,
  application: (permission) => permission.application,
  feature: (permission) => permission.feature,
  activity: (permission) => permission.activity
};
async function getMergedPermissionCatalog({
  database,
  permissions
}) {
  const [databasePermissions, configuredPermissions] = await Promise.all([
    database.select().from(permissionsInIam),
    Promise.resolve(
      getPermissionEntries(permissions).map((entry) => ({
        id: entry.code,
        description: null,
        activity: entry.activity,
        application: entry.application,
        feature: entry.feature
      }))
    )
  ]);
  return [...databasePermissions, ...configuredPermissions].filter(
    (permission, index2, permissionList) => {
      const key = [
        permission.application,
        permission.feature,
        permission.activity
      ].join(":");
      return permissionList.findIndex((candidate) => {
        return [candidate.application, candidate.feature, candidate.activity].join(
          ":"
        ) === key;
      }) === index2;
    }
  );
}
function filterAndSortPermissions(permissions, query) {
  const search = query.search?.trim().toLowerCase();
  const filteredPermissions = search ? permissions.filter((permission) => {
    let fields = [
      permission.id,
      permission.application,
      permission.feature,
      permission.activity
    ];
    if (query.filter === "application") {
      fields = [permission.application];
    } else if (query.filter === "feature") {
      fields = [permission.feature];
    } else if (query.filter === "activity") {
      fields = [permission.activity];
    }
    return fields.some((field) => field.toLowerCase().includes(search));
  }) : permissions;
  const sortGetter = sortValueMap[query.sort || "id"] ?? sortValueMap.id;
  return [...filteredPermissions].sort((a, b) => {
    const order = collator.compare(sortGetter(a), sortGetter(b)) || collator.compare(a.id, b.id);
    return query.order === "desc" ? -order : order;
  });
}
export {
  filterAndSortPermissions,
  getMergedPermissionCatalog
};
//# sourceMappingURL=permission-catalog.js.map