{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "data-retention-policy-manager",
  "title": "Data Retention Policy Manager",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/data-retention-policy-manager/DataRetentionPolicyManager.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport {\n  Archive,\n  Check,\n  CheckCircle2,\n  Clock,\n  Copy,\n  Database,\n  DollarSign,\n  HardDriveDownload,\n  MoreHorizontal,\n  Pencil,\n  Play,\n  Plus,\n  RefreshCw,\n  Search,\n  ShieldCheck,\n  FileText,\n  Info,\n  Trash2,\n  X,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { Input } from '@/components/ui/input'\nimport { Progress } from '@/components/ui/progress'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Switch } from '@/components/ui/switch'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport type EngineType = 'Snowflake' | 'BigQuery' | 'Databricks' | 'Postgres'\nexport type ArchiveTierType = 'Glacier Deep' | 'Coldline' | 'Standard Cold' | 'Purge Immediately'\n\nexport interface RetentionPolicy {\n  id: string\n  tableName: string\n  database: string\n  engine: EngineType\n  partitionColumn: string\n  retentionPeriod: string\n  lifecycleAction: string\n  archiveTier: ArchiveTierType\n  complianceReason: string\n  totalSize: string\n  coldSize: string\n  estimatedMonthlySavings: string\n  enabled: boolean\n  lastRun: string\n  nextRun: string\n  rowCount?: string\n}\n\nexport interface StorageRetentionStats {\n  totalManagedData: string\n  totalManagedSubtitle?: string\n  coldArchivedData: string\n  archivedPercentage: number\n  archivedSubtitle?: string\n  projectedMonthlySavings: string\n  savingsSubtitle?: string\n  purged30d: string\n  purgedSubtitle?: string\n}\n\ninterface Props {\n  initialPolicies?: RetentionPolicy[]\n  initialStats?: StorageRetentionStats\n  class?: HTMLAttributes['class']\n}\n\nconst defaultPolicies: RetentionPolicy[] = [\n  {\n    id: 'pol-1',\n    tableName: 'audit_logs.events',\n    database: 'SNOWFLAKE_PROD_DWH',\n    engine: 'Snowflake',\n    partitionColumn: 'event_timestamp (DAY)',\n    retentionPeriod: '90 Days Active',\n    lifecycleAction: 'Transition to Cold Glacier at 90d -> Hard Purge at 365d',\n    archiveTier: 'Glacier Deep',\n    complianceReason: 'SOX Compliance',\n    totalSize: '4.2 TB',\n    coldSize: '3.1 TB',\n    estimatedMonthlySavings: '$420.00 / mo',\n    enabled: true,\n    lastRun: '1 hour ago',\n    nextRun: 'Today at 02:00 UTC',\n    rowCount: '1.4B rows',\n  },\n  {\n    id: 'pol-2',\n    tableName: 'telemetry.raw_pings',\n    database: 'BIGQUERY_IOT_STREAM',\n    engine: 'BigQuery',\n    partitionColumn: 'received_at (HOUR)',\n    retentionPeriod: '30 Days TTL',\n    lifecycleAction: 'Direct Partition Drop at 30d TTL -> Zero Archive',\n    archiveTier: 'Purge Immediately',\n    complianceReason: 'Storage Optimization',\n    totalSize: '5.6 TB',\n    coldSize: '0.0 TB',\n    estimatedMonthlySavings: '$560.00 / mo',\n    enabled: true,\n    lastRun: '10 min ago',\n    nextRun: 'Continuous partition sweep',\n    rowCount: '8.9B rows',\n  },\n  {\n    id: 'pol-3',\n    tableName: 'billing.invoices_archive',\n    database: 'SNOWFLAKE_FINANCE',\n    engine: 'Snowflake',\n    partitionColumn: 'invoice_date (MONTH)',\n    retentionPeriod: '7 Years Compliance',\n    lifecycleAction: 'Hot 1 Year -> Glacier Vault Lock Tier 7 Years',\n    archiveTier: 'Glacier Deep',\n    complianceReason: 'SOX Compliance',\n    totalSize: '2.4 TB',\n    coldSize: '2.1 TB',\n    estimatedMonthlySavings: '$210.00 / mo',\n    enabled: true,\n    lastRun: 'Yesterday',\n    nextRun: 'Sep 01 at 00:00 UTC',\n    rowCount: '180M rows',\n  },\n  {\n    id: 'pol-4',\n    tableName: 'analytics.staging_events',\n    database: 'BIGQUERY_INGEST',\n    engine: 'BigQuery',\n    partitionColumn: 'ingest_time (DAY)',\n    retentionPeriod: '14 Days TTL',\n    lifecycleAction: 'Truncate partition > 14d -> Permanent Delete',\n    archiveTier: 'Purge Immediately',\n    complianceReason: 'Storage Optimization',\n    totalSize: '1.5 TB',\n    coldSize: '0.0 TB',\n    estimatedMonthlySavings: '$150.00 / mo',\n    enabled: false,\n    lastRun: '3 days ago',\n    nextRun: 'Paused',\n    rowCount: '420M rows',\n  },\n  {\n    id: 'pol-5',\n    tableName: 'customer_pii.user_sessions',\n    database: 'SNOWFLAKE_CUSTOMER360',\n    engine: 'Snowflake',\n    partitionColumn: 'session_start (DAY)',\n    retentionPeriod: '180 Days Active',\n    lifecycleAction: 'Anonymize at 90d -> Cold Glacier -> Hard Purge at 180d',\n    archiveTier: 'Standard Cold',\n    complianceReason: 'GDPR Art. 17',\n    totalSize: '1.1 TB',\n    coldSize: '0.9 TB',\n    estimatedMonthlySavings: '$80.00 / mo',\n    enabled: true,\n    lastRun: '6 hours ago',\n    nextRun: 'Tomorrow at 04:00 UTC',\n    rowCount: '290M rows',\n  },\n]\n\nconst defaultStats: StorageRetentionStats = {\n  totalManagedData: '14.8 TB',\n  totalManagedSubtitle: 'Across 48 partitioned tables',\n  coldArchivedData: '9.2 TB',\n  archivedPercentage: 62,\n  archivedSubtitle: '62% archived to Glacier / Cold Tier',\n  projectedMonthlySavings: '$1,420.00 / mo saved',\n  savingsSubtitle: '68% cost drop vs active NVMe',\n  purged30d: '1.8 TB',\n  purgedSubtitle: 'Expired TTL partitions purged',\n}\n\nconst props = defineProps<Props>()\n\nconst stats = computed<StorageRetentionStats>(() => props.initialStats ?? defaultStats)\nconst policies = ref<RetentionPolicy[]>([...(props.initialPolicies ?? defaultPolicies)])\nconst searchQuery = ref('')\nconst statusFilter = ref<string>('all')\nconst complianceFilter = ref<string>('all')\nconst bannerMessage = ref<{ type: 'success' | 'info'; text: string } | null>(null)\nconst copiedTable = ref<string | null>(null)\n\n// Modal States\nconst isPolicyModalOpen = ref(false)\nconst editingPolicy = ref<RetentionPolicy | null>(null)\nconst formTableName = ref('')\nconst formDatabase = ref('')\nconst formEngine = ref<EngineType>('Snowflake')\nconst formPartitionCol = ref('')\nconst formRetentionPeriod = ref('90 Days Active')\nconst formLifecycleAction = ref('Transition to Cold Glacier at 90d -> Hard Purge at 365d')\nconst formArchiveTier = ref<ArchiveTierType>('Glacier Deep')\nconst formComplianceReason = ref('SOX Compliance')\n\n// Instant Archive Modal\nconst isArchiveModalOpen = ref(false)\nconst selectedPolicyForArchive = ref<RetentionPolicy | null>(null)\nconst isArchiving = ref(false)\n\nconst filteredPolicies = computed(() => {\n  const q = searchQuery.value.trim().toLowerCase()\n  return policies.value.filter((policy) => {\n    if (statusFilter.value === 'enabled' && !policy.enabled) return false\n    if (statusFilter.value === 'disabled' && policy.enabled) return false\n\n    if (complianceFilter.value !== 'all' && policy.complianceReason !== complianceFilter.value) {\n      return false\n    }\n\n    if (!q) return true\n    const matchTable = policy.tableName.toLowerCase().includes(q)\n    const matchDb = policy.database.toLowerCase().includes(q)\n    const matchReason = policy.complianceReason.toLowerCase().includes(q)\n    const matchAction = policy.lifecycleAction.toLowerCase().includes(q)\n    const matchEngine = policy.engine.toLowerCase().includes(q)\n    return matchTable || matchDb || matchReason || matchAction || matchEngine\n  })\n})\n\nfunction togglePolicyStatus(id: string) {\n  const target = policies.value.find((p) => p.id === id)\n  if (target) {\n    target.enabled = !target.enabled\n    bannerMessage.value = {\n      type: 'info',\n      text: `Retention policy for table \"${target.tableName}\" has been ${target.enabled ? 'activated' : 'paused'}.`,\n    }\n  }\n}\n\nfunction deletePolicy(id: string) {\n  const target = policies.value.find((p) => p.id === id)\n  policies.value = policies.value.filter((p) => p.id !== id)\n  if (target) {\n    bannerMessage.value = {\n      type: 'info',\n      text: `Deleted retention policy for \"${target.tableName}\".`,\n    }\n  }\n}\n\nfunction copyTableName(name: string) {\n  if (typeof navigator !== 'undefined' && navigator.clipboard) {\n    navigator.clipboard.writeText(name)\n    copiedTable.value = name\n    setTimeout(() => {\n      if (copiedTable.value === name) copiedTable.value = null\n    }, 2000)\n  }\n}\n\nfunction openAddPolicyModal() {\n  editingPolicy.value = null\n  formTableName.value = ''\n  formDatabase.value = 'SNOWFLAKE_PROD_DWH'\n  formEngine.value = 'Snowflake'\n  formPartitionCol.value = 'created_at (DAY)'\n  formRetentionPeriod.value = '90 Days Active'\n  formLifecycleAction.value = 'Transition to Cold Glacier at 90d -> Hard Purge at 365d'\n  formArchiveTier.value = 'Glacier Deep'\n  formComplianceReason.value = 'Storage Optimization'\n  isPolicyModalOpen.value = true\n}\n\nfunction openEditPolicyModal(policy: RetentionPolicy) {\n  editingPolicy.value = policy\n  formTableName.value = policy.tableName\n  formDatabase.value = policy.database\n  formEngine.value = policy.engine\n  formPartitionCol.value = policy.partitionColumn\n  formRetentionPeriod.value = policy.retentionPeriod\n  formLifecycleAction.value = policy.lifecycleAction\n  formArchiveTier.value = policy.archiveTier\n  formComplianceReason.value = policy.complianceReason\n  isPolicyModalOpen.value = true\n}\n\nfunction savePolicy() {\n  if (!formTableName.value.trim()) return\n\n  if (editingPolicy.value) {\n    const idx = policies.value.findIndex((p) => p.id === editingPolicy.value?.id)\n    if (idx !== -1) {\n      policies.value[idx] = {\n        ...policies.value[idx],\n        tableName: formTableName.value.trim(),\n        database: formDatabase.value.trim() || 'SNOWFLAKE_PROD_DWH',\n        engine: formEngine.value,\n        partitionColumn: formPartitionCol.value.trim() || 'event_timestamp',\n        retentionPeriod: formRetentionPeriod.value,\n        lifecycleAction: formLifecycleAction.value,\n        archiveTier: formArchiveTier.value,\n        complianceReason: formComplianceReason.value,\n      }\n      bannerMessage.value = {\n        type: 'success',\n        text: `Updated retention policy for \"${formTableName.value}\".`,\n      }\n    }\n  } else {\n    const newPolicy: RetentionPolicy = {\n      id: `pol-${Date.now()}`,\n      tableName: formTableName.value.trim(),\n      database: formDatabase.value.trim() || 'SNOWFLAKE_PROD_DWH',\n      engine: formEngine.value,\n      partitionColumn: formPartitionCol.value.trim() || 'created_at (DAY)',\n      retentionPeriod: formRetentionPeriod.value,\n      lifecycleAction: formLifecycleAction.value,\n      archiveTier: formArchiveTier.value,\n      complianceReason: formComplianceReason.value,\n      totalSize: '1.2 TB',\n      coldSize: '0.8 TB',\n      estimatedMonthlySavings: '$110.00 / mo',\n      enabled: true,\n      lastRun: 'Pending First Run',\n      nextRun: 'Tonight at 00:00 UTC',\n      rowCount: '150M rows',\n    }\n    policies.value.unshift(newPolicy)\n    bannerMessage.value = {\n      type: 'success',\n      text: `Created new automated retention policy for \"${newPolicy.tableName}\".`,\n    }\n  }\n  isPolicyModalOpen.value = false\n}\n\nfunction openRunArchiveModal(policy: RetentionPolicy) {\n  selectedPolicyForArchive.value = policy\n  isArchiveModalOpen.value = true\n}\n\nfunction executeArchiveRun() {\n  if (!selectedPolicyForArchive.value) return\n  isArchiving.value = true\n\n  setTimeout(() => {\n    isArchiving.value = false\n    isArchiveModalOpen.value = false\n    const target = selectedPolicyForArchive.value\n    if (target) {\n      const idx = policies.value.findIndex((p) => p.id === target.id)\n      if (idx !== -1) {\n        policies.value[idx] = {\n          ...policies.value[idx],\n          lastRun: 'Just now',\n        }\n      }\n      bannerMessage.value = {\n        type: 'success',\n        text: `Archive partition sweep successfully completed for \"${target.tableName}\". Cold tier storage synchronized.`,\n      }\n    }\n  }, 1200)\n}\n\nfunction getRetentionBadgeVariant(\n  period: string,\n): 'default' | 'secondary' | 'outline' | 'success' | 'warning' | 'info' {\n  if (period.includes('7 Years') || period.includes('Compliance')) return 'success'\n  if (period.includes('TTL') || period.includes('14 Days') || period.includes('30 Days')) return 'warning'\n  if (period.includes('90 Days') || period.includes('180 Days')) return 'info'\n  return 'secondary'\n}\n\nfunction getComplianceBadgeVariant(\n  reason: string,\n): 'default' | 'secondary' | 'outline' | 'success' | 'warning' | 'info' {\n  if (reason.includes('GDPR') || reason.includes('CCPA')) return 'info'\n  if (reason.includes('SOX') || reason.includes('HIPAA')) return 'success'\n  if (reason.includes('Storage') || reason.includes('Optimization')) return 'secondary'\n  if (reason.includes('PCI')) return 'warning'\n  return 'outline'\n}\n</script>\n\n<template>\n  <div data-slot=\"data-retention-policy-manager\" :class=\"cn('w-full space-y-6', props.class)\">\n    <!-- Header Section -->\n    <div class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n      <div class=\"space-y-1\">\n        <div class=\"flex items-center gap-2\">\n          <div class=\"bg-primary/10 text-primary flex size-8 items-center justify-center rounded-lg\">\n            <Archive class=\"size-4.5\" />\n          </div>\n          <h1 class=\"text-foreground text-2xl font-bold tracking-tight\">Data Retention & Cold Storage Lifecycle</h1>\n        </div>\n        <p class=\"text-muted-foreground text-sm\">\n          Configure automated table partition expiration, cold storage tiering, and compliance retention periods.\n        </p>\n      </div>\n\n      <div class=\"flex items-center gap-2\">\n        <Button class=\"gap-1.5\" @click=\"openAddPolicyModal\">\n          <Plus class=\"size-4\" />\n          Add Retention Policy\n        </Button>\n      </div>\n    </div>\n\n    <!-- Notification / Action banner -->\n    <div\n      v-if=\"bannerMessage\"\n      class=\"border-border bg-card flex items-center justify-between gap-3 rounded-lg border p-3 shadow-xs\"\n    >\n      <div class=\"flex items-center gap-2.5 text-sm\">\n        <CheckCircle2 v-if=\"bannerMessage.type === 'success'\" class=\"text-success size-4 shrink-0\" />\n        <Info v-else class=\"text-primary size-4 shrink-0\" />\n        <span class=\"text-foreground text-xs font-medium sm:text-sm\">{{ bannerMessage.text }}</span>\n      </div>\n      <Button variant=\"ghost\" size=\"icon\" class=\"size-7\" @click=\"bannerMessage = null\">\n        <X class=\"size-3.5\" />\n        <span class=\"sr-only\">Dismiss</span>\n      </Button>\n    </div>\n\n    <!-- 4 Storage & Cost Impact Cards -->\n    <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n      <!-- Total Managed Data -->\n      <Card class=\"shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between pb-2\">\n          <CardTitle class=\"text-muted-foreground text-sm font-medium\">Total Managed Data</CardTitle>\n          <div class=\"bg-primary/10 text-primary rounded-lg p-2\">\n            <Database class=\"size-4\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-1\">\n          <div class=\"text-foreground text-2xl font-bold tracking-tight\">{{ stats.totalManagedData }}</div>\n          <p class=\"text-muted-foreground text-xs\">{{ stats.totalManagedSubtitle }}</p>\n        </CardContent>\n      </Card>\n\n      <!-- Auto-Archived to Glacier / Cold Tier -->\n      <Card class=\"shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between pb-2\">\n          <CardTitle class=\"text-muted-foreground text-sm font-medium\">Auto-Archived to Glacier / Cold Tier</CardTitle>\n          <div class=\"bg-success/10 text-success rounded-lg p-2\">\n            <HardDriveDownload class=\"size-4\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-2\">\n          <div class=\"flex items-center justify-between gap-x-2\">\n            <span class=\"text-foreground text-2xl font-bold tracking-tight\">{{ stats.coldArchivedData }}</span>\n            <Badge variant=\"info\" class=\"text-xs\">{{ stats.archivedPercentage }}% archived</Badge>\n          </div>\n          <Progress :model-value=\"stats.archivedPercentage\" class=\"h-1.5\" />\n          <p class=\"text-muted-foreground text-xs\">{{ stats.archivedSubtitle }}</p>\n        </CardContent>\n      </Card>\n\n      <!-- Projected Monthly Storage Savings -->\n      <Card class=\"shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between pb-2\">\n          <CardTitle class=\"text-muted-foreground text-sm font-medium\">Projected Monthly Savings</CardTitle>\n          <div class=\"bg-success/10 text-success rounded-lg p-2\">\n            <DollarSign class=\"size-4\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-1\">\n          <div class=\"flex items-center gap-2\">\n            <span class=\"text-foreground text-2xl font-bold tracking-tight\">{{ stats.projectedMonthlySavings }}</span>\n            <Badge variant=\"success\" class=\"text-xs\">Active</Badge>\n          </div>\n          <p class=\"text-muted-foreground text-xs\">{{ stats.savingsSubtitle }}</p>\n        </CardContent>\n      </Card>\n\n      <!-- Expired Data Purged in 30d -->\n      <Card class=\"shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between pb-2\">\n          <CardTitle class=\"text-muted-foreground text-sm font-medium\">Expired Data Purged (30d)</CardTitle>\n          <div class=\"bg-warning/10 text-warning rounded-lg p-2\">\n            <Trash2 class=\"size-4\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-1\">\n          <div class=\"flex items-center gap-2\">\n            <span class=\"text-foreground text-2xl font-bold tracking-tight\">{{ stats.purged30d }}</span>\n            <Badge variant=\"outline\" class=\"text-xs\">TTL Drops</Badge>\n          </div>\n          <p class=\"text-muted-foreground text-xs\">{{ stats.purgedSubtitle }}</p>\n        </CardContent>\n      </Card>\n    </div>\n\n    <!-- Retention Policies Table Card -->\n    <Card class=\"shadow-xs\">\n      <CardHeader class=\"pb-3\">\n        <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n          <div>\n            <CardTitle class=\"text-lg font-semibold\">Table Retention Policies & Partition TTL</CardTitle>\n            <CardDescription class=\"text-xs\">\n              Automated lifecycle transition rules, cold tiering, and compliance audit locks across databases.\n            </CardDescription>\n          </div>\n\n          <!-- Filter Toolbar -->\n          <div class=\"flex flex-wrap items-center gap-2\">\n            <div class=\"relative w-full sm:w-64\">\n              <Search\n                class=\"text-muted-foreground pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2\"\n              />\n              <Input\n                v-model=\"searchQuery\"\n                placeholder=\"Search table, database, or compliance...\"\n                class=\"h-8 pl-9 text-xs\"\n              />\n            </div>\n\n            <Select v-model=\"statusFilter\">\n              <SelectTrigger class=\"h-8 w-32 text-xs\">\n                <SelectValue placeholder=\"All Status\" />\n              </SelectTrigger>\n              <SelectContent>\n                <SelectItem value=\"all\">All Status</SelectItem>\n                <SelectItem value=\"enabled\">Active</SelectItem>\n                <SelectItem value=\"disabled\">Disabled</SelectItem>\n              </SelectContent>\n            </Select>\n\n            <Select v-model=\"complianceFilter\">\n              <SelectTrigger class=\"h-8 w-38 text-xs\">\n                <SelectValue placeholder=\"All Compliance\" />\n              </SelectTrigger>\n              <SelectContent>\n                <SelectItem value=\"all\">All Compliance</SelectItem>\n                <SelectItem value=\"SOX Compliance\">SOX Compliance</SelectItem>\n                <SelectItem value=\"GDPR Art. 17\">GDPR Art. 17</SelectItem>\n                <SelectItem value=\"Storage Optimization\">Storage Optimization</SelectItem>\n              </SelectContent>\n            </Select>\n          </div>\n        </div>\n      </CardHeader>\n\n      <CardContent class=\"p-0\">\n        <div class=\"overflow-x-auto\">\n          <Table>\n            <TableHeader>\n              <TableRow class=\"hover:bg-transparent\">\n                <TableHead class=\"min-w-[240px]\">Table Name & Database</TableHead>\n                <TableHead class=\"min-w-[150px]\">Retention Period</TableHead>\n                <TableHead class=\"min-w-[280px]\">Lifecycle Action & Tiering</TableHead>\n                <TableHead class=\"min-w-[150px]\">Compliance Reason</TableHead>\n                <TableHead class=\"min-w-[120px]\">Status</TableHead>\n                <TableHead class=\"w-16 text-right\">Actions</TableHead>\n              </TableRow>\n            </TableHeader>\n            <TableBody>\n              <TableRow\n                v-for=\"policy in filteredPolicies\"\n                :key=\"policy.id\"\n                :class=\"cn('group transition-colors', !policy.enabled && 'opacity-70 dark:opacity-65')\"\n              >\n                <!-- Table Name & Database -->\n                <TableCell class=\"py-3.5 align-top\">\n                  <div class=\"space-y-1\">\n                    <div class=\"flex items-center gap-1.5\">\n                      <span class=\"text-foreground font-mono text-xs font-semibold\">{{ policy.tableName }}</span>\n                      <button\n                        type=\"button\"\n                        class=\"text-muted-foreground hover:text-foreground inline-flex size-4 shrink-0 items-center justify-center transition-colors\"\n                        :title=\"copiedTable === policy.tableName ? 'Copied!' : 'Copy table name'\"\n                        @click=\"copyTableName(policy.tableName)\"\n                      >\n                        <Check v-if=\"copiedTable === policy.tableName\" class=\"text-success size-3\" />\n                        <Copy v-else class=\"size-3\" />\n                      </button>\n                    </div>\n                    <div class=\"flex flex-wrap items-center gap-1.5 text-xs\">\n                      <Badge variant=\"outline\" class=\"font-mono text-xs\">\n                        {{ policy.engine }}\n                      </Badge>\n                      <span class=\"text-muted-foreground font-mono text-xs\">{{ policy.database }}</span>\n                    </div>\n                    <div v-if=\"policy.rowCount\" class=\"text-muted-foreground text-xs\">\n                      {{ policy.rowCount }} · {{ policy.totalSize }}\n                    </div>\n                  </div>\n                </TableCell>\n\n                <!-- Retention Period Badge -->\n                <TableCell class=\"py-3.5 align-top\">\n                  <div class=\"space-y-1\">\n                    <Badge :variant=\"getRetentionBadgeVariant(policy.retentionPeriod)\" class=\"gap-1 text-xs\">\n                      <Clock class=\"size-3\" />\n                      {{ policy.retentionPeriod }}\n                    </Badge>\n                    <p class=\"text-muted-foreground font-mono text-xs\">Col: {{ policy.partitionColumn }}</p>\n                  </div>\n                </TableCell>\n\n                <!-- Lifecycle Action & Tiering -->\n                <TableCell class=\"py-3.5 align-top\">\n                  <div class=\"space-y-1\">\n                    <div class=\"text-foreground flex items-center gap-1.5 text-xs font-medium\">\n                      <Archive class=\"text-muted-foreground size-3.5 shrink-0\" />\n                      <span>{{ policy.lifecycleAction }}</span>\n                    </div>\n                    <div class=\"text-muted-foreground flex flex-wrap items-center gap-2 text-xs\">\n                      <span\n                        >Tier: <strong class=\"text-foreground font-normal\">{{ policy.archiveTier }}</strong></span\n                      >\n                      <span>·</span>\n                      <span\n                        >Savings:\n                        <span class=\"text-success font-semibold\">{{ policy.estimatedMonthlySavings }}</span></span\n                      >\n                    </div>\n                  </div>\n                </TableCell>\n\n                <!-- Compliance Reason -->\n                <TableCell class=\"py-3.5 align-top\">\n                  <div class=\"space-y-1\">\n                    <Badge :variant=\"getComplianceBadgeVariant(policy.complianceReason)\" class=\"gap-1 text-xs\">\n                      <ShieldCheck\n                        v-if=\"policy.complianceReason.includes('SOX') || policy.complianceReason.includes('GDPR')\"\n                        class=\"size-3\"\n                      />\n                      <FileText v-else class=\"size-3\" />\n                      {{ policy.complianceReason }}\n                    </Badge>\n                    <p class=\"text-muted-foreground text-xs\">Next: {{ policy.nextRun }}</p>\n                  </div>\n                </TableCell>\n\n                <!-- Status Switch -->\n                <TableCell class=\"py-3.5 align-middle\">\n                  <div class=\"flex items-center gap-2\">\n                    <Switch\n                      :model-value=\"policy.enabled\"\n                      :aria-label=\"`Toggle retention policy for ${policy.tableName}`\"\n                      @update:model-value=\"togglePolicyStatus(policy.id)\"\n                    />\n                    <span :class=\"cn('text-xs font-medium', policy.enabled ? 'text-success' : 'text-muted-foreground')\">\n                      {{ policy.enabled ? 'Enabled' : 'Disabled' }}\n                    </span>\n                  </div>\n                </TableCell>\n\n                <!-- Action Menu -->\n                <TableCell class=\"py-3.5 text-right align-middle\">\n                  <DropdownMenu>\n                    <DropdownMenuTrigger as-child>\n                      <Button variant=\"ghost\" size=\"icon\" class=\"size-8\">\n                        <MoreHorizontal class=\"size-4\" />\n                        <span class=\"sr-only\">Open actions for {{ policy.tableName }}</span>\n                      </Button>\n                    </DropdownMenuTrigger>\n                    <DropdownMenuContent align=\"end\" class=\"w-52\">\n                      <DropdownMenuLabel class=\"text-xs\">Policy Controls</DropdownMenuLabel>\n                      <DropdownMenuSeparator />\n                      <DropdownMenuItem class=\"cursor-pointer\" @click=\"openRunArchiveModal(policy)\">\n                        <Play class=\"text-success mr-2 size-4\" />\n                        <span>Run Archive Now</span>\n                      </DropdownMenuItem>\n                      <DropdownMenuItem class=\"cursor-pointer\" @click=\"openEditPolicyModal(policy)\">\n                        <Pencil class=\"mr-2 size-4\" />\n                        <span>Edit Policy</span>\n                      </DropdownMenuItem>\n                      <DropdownMenuItem class=\"cursor-pointer\" @click=\"copyTableName(policy.tableName)\">\n                        <Copy class=\"mr-2 size-4\" />\n                        <span>Copy Table Name</span>\n                      </DropdownMenuItem>\n                      <DropdownMenuSeparator />\n                      <DropdownMenuItem\n                        class=\"text-destructive focus:text-destructive cursor-pointer\"\n                        @click=\"deletePolicy(policy.id)\"\n                      >\n                        <Trash2 class=\"mr-2 size-4\" />\n                        <span>Delete Policy</span>\n                      </DropdownMenuItem>\n                    </DropdownMenuContent>\n                  </DropdownMenu>\n                </TableCell>\n              </TableRow>\n\n              <TableRow v-if=\"filteredPolicies.length === 0\">\n                <TableCell colspan=\"6\" class=\"text-muted-foreground h-32 text-center text-sm\">\n                  <div class=\"flex flex-col items-center justify-center space-y-1\">\n                    <Search class=\"text-muted-foreground/40 size-6\" />\n                    <p class=\"text-foreground text-sm font-medium\">No retention policies found</p>\n                    <p class=\"text-muted-foreground text-xs\">Try adjusting your search query or filter settings.</p>\n                  </div>\n                </TableCell>\n              </TableRow>\n            </TableBody>\n          </Table>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Add / Edit Policy Dialog -->\n    <Dialog v-model:open=\"isPolicyModalOpen\">\n      <DialogContent class=\"sm:max-w-lg\">\n        <DialogHeader>\n          <DialogTitle>{{ editingPolicy ? 'Edit Retention Policy' : 'Add Retention Policy' }}</DialogTitle>\n          <DialogDescription class=\"text-xs\">\n            Configure partition expiration time-to-live, cold tier transitions, and legal retention mandates.\n          </DialogDescription>\n        </DialogHeader>\n\n        <div class=\"space-y-3.5 py-2\">\n          <div class=\"space-y-1\">\n            <label for=\"policy-table-name\" class=\"text-foreground text-xs font-medium\"\n              >Target Table (schema.table)</label\n            >\n            <Input\n              id=\"policy-table-name\"\n              v-model=\"formTableName\"\n              placeholder=\"e.g. telemetry.clickstream_raw\"\n              class=\"font-mono text-xs\"\n            />\n          </div>\n\n          <div class=\"grid grid-cols-2 gap-3\">\n            <div class=\"space-y-1\">\n              <label for=\"policy-engine\" class=\"text-foreground text-xs font-medium\">Engine</label>\n              <Select v-model=\"formEngine\">\n                <SelectTrigger id=\"policy-engine\" class=\"text-xs\">\n                  <SelectValue placeholder=\"Engine\" />\n                </SelectTrigger>\n                <SelectContent>\n                  <SelectItem value=\"Snowflake\">Snowflake</SelectItem>\n                  <SelectItem value=\"BigQuery\">BigQuery</SelectItem>\n                  <SelectItem value=\"Databricks\">Databricks</SelectItem>\n                  <SelectItem value=\"Postgres\">Postgres</SelectItem>\n                </SelectContent>\n              </Select>\n            </div>\n\n            <div class=\"space-y-1\">\n              <label for=\"policy-database\" class=\"text-foreground text-xs font-medium\">Database / Cluster</label>\n              <Input\n                id=\"policy-database\"\n                v-model=\"formDatabase\"\n                placeholder=\"e.g. SNOWFLAKE_PROD_DWH\"\n                class=\"font-mono text-xs\"\n              />\n            </div>\n          </div>\n\n          <div class=\"grid grid-cols-2 gap-3\">\n            <div class=\"space-y-1\">\n              <label for=\"policy-partition-col\" class=\"text-foreground text-xs font-medium\">Partition Column</label>\n              <Input\n                id=\"policy-partition-col\"\n                v-model=\"formPartitionCol\"\n                placeholder=\"e.g. event_timestamp (DAY)\"\n                class=\"font-mono text-xs\"\n              />\n            </div>\n\n            <div class=\"space-y-1\">\n              <label for=\"policy-retention-period\" class=\"text-foreground text-xs font-medium\">Retention Period</label>\n              <Select v-model=\"formRetentionPeriod\">\n                <SelectTrigger id=\"policy-retention-period\" class=\"text-xs\">\n                  <SelectValue placeholder=\"Period\" />\n                </SelectTrigger>\n                <SelectContent>\n                  <SelectItem value=\"14 Days TTL\">14 Days TTL</SelectItem>\n                  <SelectItem value=\"30 Days TTL\">30 Days TTL</SelectItem>\n                  <SelectItem value=\"90 Days Active\">90 Days Active</SelectItem>\n                  <SelectItem value=\"180 Days Active\">180 Days Active</SelectItem>\n                  <SelectItem value=\"365 Days Active\">365 Days Active</SelectItem>\n                  <SelectItem value=\"7 Years Compliance\">7 Years Compliance</SelectItem>\n                </SelectContent>\n              </Select>\n            </div>\n          </div>\n\n          <div class=\"space-y-1\">\n            <label for=\"policy-lifecycle-action\" class=\"text-foreground text-xs font-medium\"\n              >Lifecycle Transition Action</label\n            >\n            <Input\n              id=\"policy-lifecycle-action\"\n              v-model=\"formLifecycleAction\"\n              placeholder=\"e.g. Transition to Cold Glacier at 90d -> Hard Purge at 365d\"\n              class=\"text-xs\"\n            />\n          </div>\n\n          <div class=\"grid grid-cols-2 gap-3\">\n            <div class=\"space-y-1\">\n              <label for=\"policy-archive-tier\" class=\"text-foreground text-xs font-medium\">Cold Storage Tier</label>\n              <Select v-model=\"formArchiveTier\">\n                <SelectTrigger id=\"policy-archive-tier\" class=\"text-xs\">\n                  <SelectValue placeholder=\"Tier\" />\n                </SelectTrigger>\n                <SelectContent>\n                  <SelectItem value=\"Glacier Deep\">Glacier Deep Archive</SelectItem>\n                  <SelectItem value=\"Coldline\">BigQuery Coldline</SelectItem>\n                  <SelectItem value=\"Standard Cold\">Standard Cold</SelectItem>\n                  <SelectItem value=\"Purge Immediately\">Purge Immediately</SelectItem>\n                </SelectContent>\n              </Select>\n            </div>\n\n            <div class=\"space-y-1\">\n              <label for=\"policy-compliance\" class=\"text-foreground text-xs font-medium\">Compliance Framework</label>\n              <Select v-model=\"formComplianceReason\">\n                <SelectTrigger id=\"policy-compliance\" class=\"text-xs\">\n                  <SelectValue placeholder=\"Compliance\" />\n                </SelectTrigger>\n                <SelectContent>\n                  <SelectItem value=\"SOX Compliance\">SOX Compliance</SelectItem>\n                  <SelectItem value=\"GDPR Art. 17\">GDPR Art. 17</SelectItem>\n                  <SelectItem value=\"Storage Optimization\">Storage Optimization</SelectItem>\n                  <SelectItem value=\"PCI-DSS v4.0\">PCI-DSS v4.0</SelectItem>\n                </SelectContent>\n              </Select>\n            </div>\n          </div>\n        </div>\n\n        <DialogFooter>\n          <Button variant=\"outline\" @click=\"isPolicyModalOpen = false\">Cancel</Button>\n          <Button :disabled=\"!formTableName.trim()\" @click=\"savePolicy\">\n            {{ editingPolicy ? 'Save Policy Changes' : 'Create Retention Policy' }}\n          </Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n\n    <!-- Run Archive Dry-Run & Execution Modal -->\n    <Dialog v-model:open=\"isArchiveModalOpen\">\n      <DialogContent class=\"sm:max-w-md\">\n        <DialogHeader>\n          <div class=\"flex items-center gap-2\">\n            <div class=\"bg-primary/10 text-primary rounded-lg p-2\">\n              <HardDriveDownload class=\"size-5\" />\n            </div>\n            <div>\n              <DialogTitle>Run Archive Partition Sweep</DialogTitle>\n              <DialogDescription class=\"text-xs\">\n                Trigger manual partition evaluation and transition expired partitions to cold storage.\n              </DialogDescription>\n            </div>\n          </div>\n        </DialogHeader>\n\n        <div class=\"space-y-3 py-2 text-xs\">\n          <div class=\"border-border bg-muted/40 space-y-2 rounded-lg border p-3\">\n            <div class=\"flex items-center justify-between gap-x-2\">\n              <span class=\"text-muted-foreground\">Target Table:</span>\n              <span class=\"text-foreground font-mono font-semibold\">{{ selectedPolicyForArchive?.tableName }}</span>\n            </div>\n            <div class=\"flex items-center justify-between gap-x-2\">\n              <span class=\"text-muted-foreground\">Database Engine:</span>\n              <Badge variant=\"outline\" class=\"font-mono text-xs\">{{ selectedPolicyForArchive?.engine }}</Badge>\n            </div>\n            <div class=\"flex items-center justify-between gap-x-2\">\n              <span class=\"text-muted-foreground\">Lifecycle Action:</span>\n              <span class=\"text-foreground font-medium\">{{ selectedPolicyForArchive?.lifecycleAction }}</span>\n            </div>\n            <div class=\"flex items-center justify-between gap-x-2\">\n              <span class=\"text-muted-foreground\">Est. Savings:</span>\n              <span class=\"text-success font-semibold\">{{ selectedPolicyForArchive?.estimatedMonthlySavings }}</span>\n            </div>\n          </div>\n\n          <div class=\"border-border bg-card text-muted-foreground space-y-1 rounded-lg border p-3\">\n            <div class=\"text-foreground flex items-center gap-1.5 font-medium\">\n              <ShieldCheck class=\"text-success size-4\" />\n              <span>Dry-Run Check Passed</span>\n            </div>\n            <p class=\"text-xs\">\n              Partitions older than configured threshold will be compressed, archived into cold tier, and purged from\n              active storage without table locks.\n            </p>\n          </div>\n        </div>\n\n        <DialogFooter>\n          <Button variant=\"outline\" :disabled=\"isArchiving\" @click=\"isArchiveModalOpen = false\">Cancel</Button>\n          <Button :disabled=\"isArchiving\" class=\"gap-1.5\" @click=\"executeArchiveRun\">\n            <RefreshCw v-if=\"isArchiving\" class=\"size-4 animate-spin\" />\n            <Play v-else class=\"size-4\" />\n            {{ isArchiving ? 'Archiving Partitions...' : 'Run Archive Sweep Now' }}\n          </Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/DataRetentionPolicyManager.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/dialog.json",
    "https://uipkge.dev/r/vue/dropdown-menu.json",
    "https://uipkge.dev/r/vue/input.json",
    "https://uipkge.dev/r/vue/progress.json",
    "https://uipkge.dev/r/vue/select.json",
    "https://uipkge.dev/r/vue/switch.json",
    "https://uipkge.dev/r/vue/table.json"
  ],
  "description": "Snowflake and BigQuery style automated data retention policy manager, partition TTL scheduler, and cold storage archive tiering with cost impact metrics, lifecycle action execution, and compliance tracking.",
  "categories": [
    "devops",
    "dashboard",
    "app",
    "data"
  ]
}