diff --git a/apps/dashboard/drizzle/0034_base_image_variants.sql b/apps/dashboard/drizzle/0034_base_image_variants.sql new file mode 100644 index 00000000..c05c9eee --- /dev/null +++ b/apps/dashboard/drizzle/0034_base_image_variants.sql @@ -0,0 +1,3 @@ +DROP VIEW "analytics"."base_images";--> statement-breakpoint +ALTER TABLE "base_images" ADD COLUMN "variant" text DEFAULT '' NOT NULL;--> statement-breakpoint +CREATE VIEW "analytics"."base_images" AS (select "id", "file_path", "name", "version", "variant", "description", "short_name", "icon", "color", "is_official", "logo_svg", "accent_color", "image_type", "secure_boot", "isa", "sort_order" from "base_images"); \ No newline at end of file diff --git a/apps/dashboard/drizzle/meta/0034_snapshot.json b/apps/dashboard/drizzle/meta/0034_snapshot.json new file mode 100644 index 00000000..096589e5 --- /dev/null +++ b/apps/dashboard/drizzle/meta/0034_snapshot.json @@ -0,0 +1,3809 @@ +{ + "id": "4ba7af56-ed45-4657-9fc7-46523bede1e5", + "prevId": "c7b6a47c-f933-4600-974a-3f7a8fde0c1e", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.api_tokens": { + "name": "api_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "api_tokens_user_id_index": { + "name": "api_tokens_user_id_index", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.base_images": { + "name": "base_images", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "file_path": { + "name": "file_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variant": { + "name": "variant", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "short_name": { + "name": "short_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'bg-gray-600'" + }, + "is_official": { + "name": "is_official", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "logo_svg": { + "name": "logo_svg", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accent_color": { + "name": "accent_color", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'#6b7280'" + }, + "image_type": { + "name": "image_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'qcow2'" + }, + "secure_boot": { + "name": "secure_boot", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "isa": { + "name": "isa", + "type": "vm_isa", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.billing_meters": { + "name": "billing_meters", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_type": { + "name": "resource_type", + "type": "billing_resource_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "feature_id": { + "name": "feature_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "units": { + "name": "units", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "last_metered_at": { + "name": "last_metered_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "cap_period_start": { + "name": "cap_period_start", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "cap_period_end": { + "name": "cap_period_end", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "hours_this_period": { + "name": "hours_this_period", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "ended_at": { + "name": "ended_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "billing_meters_resource_index": { + "name": "billing_meters_resource_index", + "columns": [ + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "billing_meters_active_last_metered_at_index": { + "name": "billing_meters_active_last_metered_at_index", + "columns": [ + { + "expression": "active", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_metered_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "billing_meters_project_active_index": { + "name": "billing_meters_project_active_index", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.billing_usage_events": { + "name": "billing_usage_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_type": { + "name": "resource_type", + "type": "billing_resource_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "feature_id": { + "name": "feature_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "period_start": { + "name": "period_start", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "period_end": { + "name": "period_end", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "idempotency_key": { + "name": "idempotency_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "billing_sync_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "synced_at": { + "name": "synced_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "billing_usage_events_idempotency_key_index": { + "name": "billing_usage_events_idempotency_key_index", + "columns": [ + { + "expression": "idempotency_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "billing_usage_events_project_created_at_index": { + "name": "billing_usage_events_project_created_at_index", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "billing_usage_events_sync_status_created_at_index": { + "name": "billing_usage_events_sync_status_created_at_index", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "billing_usage_events_resource_index": { + "name": "billing_usage_events_resource_index", + "columns": [ + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.idempotency_keys": { + "name": "idempotency_keys", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "fingerprint": { + "name": "fingerprint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "idempotency_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "result": { + "name": "result", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + }, + "updated_at": { + "name": "updated_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + }, + "expires_at": { + "name": "expires_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idempotency_keys_expires_at_index": { + "name": "idempotency_keys_expires_at_index", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ip_assignments": { + "name": "ip_assignments", + "schema": "", + "columns": { + "ip": { + "name": "ip", + "type": "inet", + "primaryKey": false, + "notNull": true + }, + "ip_block_id": { + "name": "ip_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "associated_vm_id": { + "name": "associated_vm_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "ip_assignments_ip_block_id_index": { + "name": "ip_assignments_ip_block_id_index", + "columns": [ + { + "expression": "ip_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ip_assignments_associated_vm_id_index": { + "name": "ip_assignments_associated_vm_id_index", + "columns": [ + { + "expression": "associated_vm_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ip_assignments_ip_block_id_ip_blocks_id_fk": { + "name": "ip_assignments_ip_block_id_ip_blocks_id_fk", + "tableFrom": "ip_assignments", + "tableTo": "ip_blocks", + "columnsFrom": [ + "ip_block_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "ip_assignments_associated_vm_id_vms_id_fk": { + "name": "ip_assignments_associated_vm_id_vms_id_fk", + "tableFrom": "ip_assignments", + "tableTo": "vms", + "columnsFrom": [ + "associated_vm_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ip_blocks": { + "name": "ip_blocks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ip_block": { + "name": "ip_block", + "type": "cidr", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ipam_allocations": { + "name": "ipam_allocations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ipam_prefix_id": { + "name": "ipam_prefix_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "associated_vm_id": { + "name": "associated_vm_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "family": { + "name": "family", + "type": "ip_family", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "address": { + "name": "address", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "prefix": { + "name": "prefix", + "type": "cidr", + "primaryKey": false, + "notNull": false + }, + "prefix_length": { + "name": "prefix_length", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "mac_address": { + "name": "mac_address", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + } + }, + "indexes": { + "ipam_allocations_ipam_prefix_id_index": { + "name": "ipam_allocations_ipam_prefix_id_index", + "columns": [ + { + "expression": "ipam_prefix_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ipam_allocations_associated_vm_id_index": { + "name": "ipam_allocations_associated_vm_id_index", + "columns": [ + { + "expression": "associated_vm_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ipam_allocations_vm_family_index": { + "name": "ipam_allocations_vm_family_index", + "columns": [ + { + "expression": "associated_vm_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "family", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ipam_allocations_address_index": { + "name": "ipam_allocations_address_index", + "columns": [ + { + "expression": "address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ipam_allocations_prefix_index": { + "name": "ipam_allocations_prefix_index", + "columns": [ + { + "expression": "prefix", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ipam_allocations_ipam_prefix_id_ipam_prefixes_id_fk": { + "name": "ipam_allocations_ipam_prefix_id_ipam_prefixes_id_fk", + "tableFrom": "ipam_allocations", + "tableTo": "ipam_prefixes", + "columnsFrom": [ + "ipam_prefix_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "ipam_allocations_associated_vm_id_vms_id_fk": { + "name": "ipam_allocations_associated_vm_id_vms_id_fk", + "tableFrom": "ipam_allocations", + "tableTo": "vms", + "columnsFrom": [ + "associated_vm_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ipam_prefixes": { + "name": "ipam_prefixes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "cidr": { + "name": "cidr", + "type": "cidr", + "primaryKey": false, + "notNull": true + }, + "family": { + "name": "family", + "type": "ip_family", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "ipv6_use_transit_address": { + "name": "ipv6_use_transit_address", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "whitelist_start": { + "name": "whitelist_start", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "whitelist_end": { + "name": "whitelist_end", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "gateway_address": { + "name": "gateway_address", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "bunny_dns_zone": { + "name": "bunny_dns_zone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + } + }, + "indexes": { + "ipam_prefixes_cidr_index": { + "name": "ipam_prefixes_cidr_index", + "columns": [ + { + "expression": "cidr", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ipam_prefixes_family_disabled_index": { + "name": "ipam_prefixes_family_disabled_index", + "columns": [ + { + "expression": "family", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "disabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ipam_ptr_records": { + "name": "ipam_ptr_records", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ipam_allocation_id": { + "name": "ipam_allocation_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address": { + "name": "address", + "type": "inet", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "bunny_record_id": { + "name": "bunny_record_id", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + } + }, + "indexes": { + "ipam_ptr_records_ipam_allocation_id_index": { + "name": "ipam_ptr_records_ipam_allocation_id_index", + "columns": [ + { + "expression": "ipam_allocation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ipam_ptr_records_address_index": { + "name": "ipam_ptr_records_address_index", + "columns": [ + { + "expression": "address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ipam_ptr_records_ipam_allocation_id_ipam_allocations_id_fk": { + "name": "ipam_ptr_records_ipam_allocation_id_ipam_allocations_id_fk", + "tableFrom": "ipam_ptr_records", + "tableTo": "ipam_allocations", + "columnsFrom": [ + "ipam_allocation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ipam_settings": { + "name": "ipam_settings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "default_ptr_format_ipv4": { + "name": "default_ptr_format_ipv4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "default_ptr_format_ipv6": { + "name": "default_ptr_format_ipv6", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payment_periods": { + "name": "payment_periods", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "vm_id": { + "name": "vm_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "start_date": { + "name": "start_date", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "end_date": { + "name": "end_date", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rate": { + "name": "rate", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "cap": { + "name": "cap", + "type": "numeric", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "payment_periods_vm_id_index": { + "name": "payment_periods_vm_id_index", + "columns": [ + { + "expression": "vm_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payment_periods_user_id_index": { + "name": "payment_periods_user_id_index", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "payment_periods_vm_id_vms_id_fk": { + "name": "payment_periods_vm_id_vms_id_fk", + "tableFrom": "payment_periods", + "tableTo": "vms", + "columnsFrom": [ + "vm_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.project_billing_customers": { + "name": "project_billing_customers", + "schema": "", + "columns": { + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "autumn_customer_id": { + "name": "autumn_customer_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sync_status": { + "name": "sync_status", + "type": "billing_sync_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "past_due_since": { + "name": "past_due_since", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "suspended_at": { + "name": "suspended_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "project_billing_customers_autumn_customer_id_index": { + "name": "project_billing_customers_autumn_customer_id_index", + "columns": [ + { + "expression": "autumn_customer_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ssh_keys": { + "name": "ssh_keys", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "fingerprint": { + "name": "fingerprint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "ssh_keys_user_id_index": { + "name": "ssh_keys_user_id_index", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.vm_types": { + "name": "vm_types", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isa": { + "name": "isa", + "type": "vm_isa", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "cores": { + "name": "cores", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "ram_capacity": { + "name": "ram_capacity", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "storage_amount": { + "name": "storage_amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "rate": { + "name": "rate", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "cap": { + "name": "cap", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "autumn_feature_id": { + "name": "autumn_feature_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.vms": { + "name": "vms", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "proxmox_id": { + "name": "proxmox_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "proxmox_node": { + "name": "proxmox_node", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_known_ipv4": { + "name": "last_known_ipv4", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "last_known_ipv6": { + "name": "last_known_ipv6", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "last_known_status": { + "name": "last_known_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_known_uptime": { + "name": "last_known_uptime", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_known_at": { + "name": "last_known_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "owner_project_id": { + "name": "owner_project_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "vm_type_id": { + "name": "vm_type_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "creation_date": { + "name": "creation_date", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + }, + "backend": { + "name": "backend", + "type": "vm_backend", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "vm_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'provisioning'" + }, + "status_error": { + "name": "status_error", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "vms_owner_project_id_index": { + "name": "vms_owner_project_id_index", + "columns": [ + { + "expression": "owner_project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "vms_owner_project_active_index": { + "name": "vms_owner_project_active_index", + "columns": [ + { + "expression": "owner_project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "vms_proxmox_id_index": { + "name": "vms_proxmox_id_index", + "columns": [ + { + "expression": "proxmox_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "vms_active_proxmox_id_unique": { + "name": "vms_active_proxmox_id_unique", + "columns": [ + { + "expression": "proxmox_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"vms\".\"active\"", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "vms_owner_project_id_organization_id_fk": { + "name": "vms_owner_project_id_organization_id_fk", + "tableFrom": "vms", + "tableTo": "organization", + "columnsFrom": [ + "owner_project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "vms_vm_type_id_vm_types_id_fk": { + "name": "vms_vm_type_id_vm_types_id_fk", + "tableFrom": "vms", + "tableTo": "vm_types", + "columnsFrom": [ + "vm_type_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.volumes": { + "name": "volumes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "owner_project_id": { + "name": "owner_project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "associated_vm_id": { + "name": "associated_vm_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + } + }, + "indexes": { + "volumes_owner_project_id_index": { + "name": "volumes_owner_project_id_index", + "columns": [ + { + "expression": "owner_project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "volumes_associated_vm_id_index": { + "name": "volumes_associated_vm_id_index", + "columns": [ + { + "expression": "associated_vm_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "volumes_owner_project_id_organization_id_fk": { + "name": "volumes_owner_project_id_organization_id_fk", + "tableFrom": "volumes", + "tableTo": "organization", + "columnsFrom": [ + "owner_project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "volumes_associated_vm_id_vms_id_fk": { + "name": "volumes_associated_vm_id_vms_id_fk", + "tableFrom": "volumes", + "tableTo": "vms", + "columnsFrom": [ + "associated_vm_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "invitation_organizationId_idx": { + "name": "invitation_organizationId_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitation_email_idx": { + "name": "invitation_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "invitation_organization_id_organization_id_fk": { + "name": "invitation_organization_id_organization_id_fk", + "tableFrom": "invitation", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_inviter_id_user_id_fk": { + "name": "invitation_inviter_id_user_id_fk", + "tableFrom": "invitation", + "tableTo": "user", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.member": { + "name": "member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "member_organizationId_idx": { + "name": "member_organizationId_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "member_userId_idx": { + "name": "member_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "member_organization_id_organization_id_fk": { + "name": "member_organization_id_organization_id_fk", + "tableFrom": "member", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_user_id_user_id_fk": { + "name": "member_user_id_user_id_fk", + "tableFrom": "member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization": { + "name": "organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "billing_exempt": { + "name": "billing_exempt", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "organization_slug_uidx": { + "name": "organization_slug_uidx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "organization_slug_unique": { + "name": "organization_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.passkey": { + "name": "passkey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "counter": { + "name": "counter", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "backed_up": { + "name": "backed_up", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "transports": { + "name": "transports", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "aaguid": { + "name": "aaguid", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "passkey_userId_idx": { + "name": "passkey_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "passkey_credentialID_idx": { + "name": "passkey_credentialID_idx", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "passkey_user_id_user_id_fk": { + "name": "passkey_user_id_user_id_fk", + "tableFrom": "passkey", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.two_factor": { + "name": "two_factor", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "backup_codes": { + "name": "backup_codes", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "failed_verification_count": { + "name": "failed_verification_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "locked_until": { + "name": "locked_until", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "twoFactor_secret_idx": { + "name": "twoFactor_secret_idx", + "columns": [ + { + "expression": "secret", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "twoFactor_userId_idx": { + "name": "twoFactor_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "two_factor_user_id_user_id_fk": { + "name": "two_factor_user_id_user_id_fk", + "tableFrom": "two_factor", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "two_factor_enabled": { + "name": "two_factor_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "billing_exempt": { + "name": "billing_exempt", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.billing_resource_type": { + "name": "billing_resource_type", + "schema": "public", + "values": [ + "vm", + "volume" + ] + }, + "public.billing_sync_status": { + "name": "billing_sync_status", + "schema": "public", + "values": [ + "pending", + "synced", + "failed", + "abandoned" + ] + }, + "public.idempotency_status": { + "name": "idempotency_status", + "schema": "public", + "values": [ + "pending", + "completed" + ] + }, + "public.ip_family": { + "name": "ip_family", + "schema": "public", + "values": [ + "ipv4", + "ipv6" + ] + }, + "public.vm_backend": { + "name": "vm_backend", + "schema": "public", + "values": [ + "proxmox" + ] + }, + "public.vm_isa": { + "name": "vm_isa", + "schema": "public", + "values": [ + "x86", + "arm", + "risc-v" + ] + }, + "public.vm_status": { + "name": "vm_status", + "schema": "public", + "values": [ + "provisioning", + "ready", + "error", + "deleting" + ] + } + }, + "schemas": { + "analytics": "analytics" + }, + "sequences": { + "public.proxmox_vmid_seq": { + "name": "proxmox_vmid_seq", + "schema": "public", + "increment": "1", + "startWith": "1000", + "minValue": "1000", + "maxValue": "999999999", + "cache": "1", + "cycle": false + } + }, + "roles": {}, + "policies": {}, + "views": { + "analytics.api_tokens": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "definition": "select \"id\", \"user_id\", \"created_at\" from \"api_tokens\"", + "name": "api_tokens", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.base_images": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "file_path": { + "name": "file_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variant": { + "name": "variant", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "short_name": { + "name": "short_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'bg-gray-600'" + }, + "is_official": { + "name": "is_official", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "logo_svg": { + "name": "logo_svg", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accent_color": { + "name": "accent_color", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'#6b7280'" + }, + "image_type": { + "name": "image_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'qcow2'" + }, + "secure_boot": { + "name": "secure_boot", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "isa": { + "name": "isa", + "type": "vm_isa", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "definition": "select \"id\", \"file_path\", \"name\", \"version\", \"variant\", \"description\", \"short_name\", \"icon\", \"color\", \"is_official\", \"logo_svg\", \"accent_color\", \"image_type\", \"secure_boot\", \"isa\", \"sort_order\" from \"base_images\"", + "name": "base_images", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.billing_meters": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_type": { + "name": "resource_type", + "type": "billing_resource_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "feature_id": { + "name": "feature_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "units": { + "name": "units", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "last_metered_at": { + "name": "last_metered_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "ended_at": { + "name": "ended_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "definition": "select \"id\", \"project_id\", \"resource_type\", \"resource_id\", \"feature_id\", \"units\", \"last_metered_at\", \"active\", \"created_at\", \"ended_at\" from \"billing_meters\"", + "name": "billing_meters", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.billing_usage_events": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_type": { + "name": "resource_type", + "type": "billing_resource_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "feature_id": { + "name": "feature_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "period_start": { + "name": "period_start", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "period_end": { + "name": "period_end", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "idempotency_key": { + "name": "idempotency_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sync_status": { + "name": "sync_status", + "type": "billing_sync_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "synced_at": { + "name": "synced_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "definition": "select \"id\", \"project_id\", \"resource_type\", \"resource_id\", \"feature_id\", \"quantity\", \"period_start\", \"period_end\", \"idempotency_key\", \"sync_status\", \"sync_error\", \"synced_at\", \"created_at\" from \"billing_usage_events\"", + "name": "billing_usage_events", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.ipam_allocations": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ipam_prefix_id": { + "name": "ipam_prefix_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "associated_vm_id": { + "name": "associated_vm_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "family": { + "name": "family", + "type": "ip_family", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "address": { + "name": "address", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "prefix": { + "name": "prefix", + "type": "cidr", + "primaryKey": false, + "notNull": false + }, + "prefix_length": { + "name": "prefix_length", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + } + }, + "definition": "select \"id\", \"ipam_prefix_id\", \"associated_vm_id\", \"family\", \"address\", \"prefix\", \"prefix_length\", \"created_at\" from \"ipam_allocations\"", + "name": "ipam_allocations", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.ipam_prefixes": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "cidr": { + "name": "cidr", + "type": "cidr", + "primaryKey": false, + "notNull": true + }, + "family": { + "name": "family", + "type": "ip_family", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "ipv6_use_transit_address": { + "name": "ipv6_use_transit_address", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "whitelist_start": { + "name": "whitelist_start", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "whitelist_end": { + "name": "whitelist_end", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "gateway_address": { + "name": "gateway_address", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + } + }, + "definition": "select \"id\", \"name\", \"cidr\", \"family\", \"disabled\", \"ipv6_use_transit_address\", \"whitelist_start\", \"whitelist_end\", \"gateway_address\", \"created_at\" from \"ipam_prefixes\"", + "name": "ipam_prefixes", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.ipam_ptr_records": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ipam_allocation_id": { + "name": "ipam_allocation_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address": { + "name": "address", + "type": "inet", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + } + }, + "definition": "select \"id\", \"ipam_allocation_id\", \"address\", \"value\", \"created_at\" from \"ipam_ptr_records\"", + "name": "ipam_ptr_records", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.ipam_settings": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "default_ptr_format_ipv4": { + "name": "default_ptr_format_ipv4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "default_ptr_format_ipv6": { + "name": "default_ptr_format_ipv6", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "definition": "select \"id\", \"default_ptr_format_ipv4\", \"default_ptr_format_ipv6\" from \"ipam_settings\"", + "name": "ipam_settings", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.member": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "definition": "select \"id\", \"organization_id\", \"user_id\", \"role\", \"created_at\" from \"member\"", + "name": "member", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.organization": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "billing_exempt": { + "name": "billing_exempt", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "definition": "select \"id\", \"name\", \"slug\", \"created_at\", \"billing_exempt\", \"disabled\", \"deleted_at\" from \"organization\"", + "name": "organization", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.project_billing_customers": { + "columns": { + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "sync_status": { + "name": "sync_status", + "type": "billing_sync_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "past_due_since": { + "name": "past_due_since", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "suspended_at": { + "name": "suspended_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "definition": "select \"project_id\", \"sync_status\", \"sync_error\", \"last_synced_at\", \"past_due_since\", \"suspended_at\", \"created_at\", \"updated_at\" from \"project_billing_customers\"", + "name": "project_billing_customers", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.ssh_keys": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "fingerprint": { + "name": "fingerprint", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "definition": "select \"id\", \"user_id\", \"fingerprint\" from \"ssh_keys\"", + "name": "ssh_keys", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.user": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "two_factor_enabled": { + "name": "two_factor_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "billing_exempt": { + "name": "billing_exempt", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "definition": "select \"id\", \"email_verified\", \"created_at\", \"updated_at\", \"role\", \"banned\", \"ban_expires\", \"two_factor_enabled\", \"is_admin\", \"billing_exempt\" from \"user\"", + "name": "user", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.vm_types": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isa": { + "name": "isa", + "type": "vm_isa", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "cores": { + "name": "cores", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "ram_capacity": { + "name": "ram_capacity", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "storage_amount": { + "name": "storage_amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "rate": { + "name": "rate", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "cap": { + "name": "cap", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "definition": "select \"id\", \"name\", \"isa\", \"cores\", \"ram_capacity\", \"storage_amount\", \"rate\", \"cap\", \"sort_order\" from \"vm_types\"", + "name": "vm_types", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.vms": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "proxmox_id": { + "name": "proxmox_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "proxmox_node": { + "name": "proxmox_node", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_known_ipv4": { + "name": "last_known_ipv4", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "last_known_ipv6": { + "name": "last_known_ipv6", + "type": "inet", + "primaryKey": false, + "notNull": false + }, + "last_known_status": { + "name": "last_known_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_known_uptime": { + "name": "last_known_uptime", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_known_at": { + "name": "last_known_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "owner_project_id": { + "name": "owner_project_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "vm_type_id": { + "name": "vm_type_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "creation_date": { + "name": "creation_date", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + }, + "backend": { + "name": "backend", + "type": "vm_backend", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "vm_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'provisioning'" + }, + "status_error": { + "name": "status_error", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "definition": "select \"id\", \"proxmox_id\", \"proxmox_node\", \"last_known_ipv4\", \"last_known_ipv6\", \"last_known_status\", \"last_known_uptime\", \"last_known_at\", \"active\", \"deleted_at\", \"owner_project_id\", \"vm_type_id\", \"creation_date\", \"created_at\", \"backend\", \"status\", \"status_error\" from \"vms\"", + "name": "vms", + "schema": "analytics", + "isExisting": false, + "materialized": false + }, + "analytics.volumes": { + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "owner_project_id": { + "name": "owner_project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "associated_vm_id": { + "name": "associated_vm_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": "(extract(epoch from now()) * 1000)::bigint" + } + }, + "definition": "select \"id\", \"size\", \"owner_project_id\", \"associated_vm_id\", \"created_at\" from \"volumes\"", + "name": "volumes", + "schema": "analytics", + "isExisting": false, + "materialized": false + } + }, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/dashboard/drizzle/meta/_journal.json b/apps/dashboard/drizzle/meta/_journal.json index f9586342..cd12df0f 100644 --- a/apps/dashboard/drizzle/meta/_journal.json +++ b/apps/dashboard/drizzle/meta/_journal.json @@ -239,6 +239,13 @@ "when": 1791959839230, "tag": "0033_idempotency_keys", "breakpoints": true + }, + { + "idx": 34, + "version": "7", + "when": 1792971629616, + "tag": "0034_base_image_variants", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/dashboard/src/lib/remote/images.remote.ts b/apps/dashboard/src/lib/remote/images.remote.ts index 40016d51..ab1d7638 100644 --- a/apps/dashboard/src/lib/remote/images.remote.ts +++ b/apps/dashboard/src/lib/remote/images.remote.ts @@ -67,6 +67,7 @@ export const listImages = query(async () => { filePath: row.filePath, name: row.name, version: row.version, + variant: row.variant, description: row.description, icon: row.icon, color: row.color, @@ -82,6 +83,7 @@ export const listImages = query(async () => { const createParams = type({ name: 'string', version: 'string', + variant: 'string?', description: 'string', icon: 'string?', color: 'string?', @@ -119,6 +121,7 @@ export const createImage = command(createParams, async (params) => { sortOrder: (lastImage?.sortOrder ?? -1) + 1, name: params.name, version: params.version, + variant: params.variant?.trim() ?? '', description: params.description, icon: params.icon, color: params.color ?? 'bg-gray-600', @@ -139,6 +142,7 @@ const updateParams = type({ imageId: 'string', name: 'string?', version: 'string?', + variant: 'string?', description: 'string?', icon: 'string?', color: 'string?', @@ -169,6 +173,9 @@ export const updateImage = command(updateParams, async (params) => { const updates: Record = Object.fromEntries( Object.entries(fields).filter(([, v]) => v !== undefined) ); + if (typeof updates.variant === 'string') { + updates.variant = updates.variant.trim(); + } if (updates.filePath) { const selectedImage = await getUploadedImage(String(updates.filePath)); if (!selectedImage) { diff --git a/apps/dashboard/src/lib/server/accessibility-fixtures.ts b/apps/dashboard/src/lib/server/accessibility-fixtures.ts index ca67c24f..30757306 100644 --- a/apps/dashboard/src/lib/server/accessibility-fixtures.ts +++ b/apps/dashboard/src/lib/server/accessibility-fixtures.ts @@ -252,6 +252,7 @@ export const accessibilityFixtureImages = [ id: 'ubuntu-2404', name: 'Ubuntu', version: '24.04 LTS', + variant: '', description: 'Ubuntu 24.04 LTS', icon: 'ubuntu', color: 'bg-orange-500', diff --git a/apps/dashboard/src/lib/server/db/analytics.schema.ts b/apps/dashboard/src/lib/server/db/analytics.schema.ts index 566aa8c9..0def8f61 100644 --- a/apps/dashboard/src/lib/server/db/analytics.schema.ts +++ b/apps/dashboard/src/lib/server/db/analytics.schema.ts @@ -280,6 +280,7 @@ export const analyticsBaseImages = analyticsSchema.view('base_images').as((qb) = filePath: baseImages.filePath, name: baseImages.name, version: baseImages.version, + variant: baseImages.variant, description: baseImages.description, shortName: baseImages.shortName, icon: baseImages.icon, diff --git a/apps/dashboard/src/lib/server/db/schema.ts b/apps/dashboard/src/lib/server/db/schema.ts index 42e3503c..f8f6a664 100644 --- a/apps/dashboard/src/lib/server/db/schema.ts +++ b/apps/dashboard/src/lib/server/db/schema.ts @@ -442,6 +442,7 @@ export const baseImages = pgTable('base_images', { filePath: text('file_path').notNull(), // Proxmox storage path: "local:import/debian-12.qcow2" name: text('name').notNull(), version: text('version').notNull(), + variant: text('variant').notNull().default(''), // e.g. "systemd" / "openrc"; '' = default description: text('description').notNull(), shortName: text('short_name').notNull().default(''), icon: text('icon'), diff --git a/apps/dashboard/src/lib/state/admin.svelte.ts b/apps/dashboard/src/lib/state/admin.svelte.ts index 3123c5e6..94929f6c 100644 --- a/apps/dashboard/src/lib/state/admin.svelte.ts +++ b/apps/dashboard/src/lib/state/admin.svelte.ts @@ -82,6 +82,7 @@ export interface BaseImage { logoSvg: string | null | undefined; name: string; secureBoot: boolean; + variant: string; version: string; } @@ -226,6 +227,7 @@ export class AdminState { imgError = $state(''); imgName = $state(''); imgVersion = $state(''); + imgVariant = $state(''); imgDescription = $state(''); imgIcon = $state(''); imgColor = $state('bg-gray-600'); @@ -748,6 +750,7 @@ export class AdminState { this.imgEditing = null; this.imgName = ''; this.imgVersion = ''; + this.imgVariant = ''; this.imgDescription = ''; this.imgIcon = ''; this.imgColor = 'bg-gray-600'; @@ -768,6 +771,7 @@ export class AdminState { this.imgEditing = img; this.imgName = img.name; this.imgVersion = img.version; + this.imgVariant = img.variant; this.imgDescription = img.description; this.imgIcon = img.icon ?? ''; this.imgColor = img.color; @@ -797,6 +801,7 @@ export class AdminState { const data = { name: this.imgName.trim(), version: this.imgVersion.trim(), + variant: this.imgVariant.trim(), description: this.imgDescription.trim(), color: this.imgColor, isOfficial: this.imgIsOfficial, diff --git a/apps/dashboard/src/routes/(app)/admin/images/+page.svelte b/apps/dashboard/src/routes/(app)/admin/images/+page.svelte index 295717e7..ad43d5f8 100644 --- a/apps/dashboard/src/routes/(app)/admin/images/+page.svelte +++ b/apps/dashboard/src/routes/(app)/admin/images/+page.svelte @@ -180,7 +180,12 @@ - {img.version} + + {img.version} + {#if img.variant} + {img.variant} + {/if} + {img.imageType || 'import'} @@ -382,6 +387,20 @@ +
+ + +

+ Images with the same name are grouped into one card. Variants and versions are picked from + that card when creating a server. +

+
+
diff --git a/apps/dashboard/src/routes/(app)/admin/projects/[[id]]/+page.svelte b/apps/dashboard/src/routes/(app)/admin/projects/[[id]]/+page.svelte index 875d4a19..39fb4c5d 100644 --- a/apps/dashboard/src/routes/(app)/admin/projects/[[id]]/+page.svelte +++ b/apps/dashboard/src/routes/(app)/admin/projects/[[id]]/+page.svelte @@ -277,7 +277,9 @@ ); const createVmImageLabel = $derived.by(() => { const image = admin.images.find((item) => item.id === createVmImageId); - return image ? `${image.name} ${image.version}`.trim() : 'No image'; + return image + ? [image.name, image.version, image.variant].filter(Boolean).join(' ') + : 'No image'; }); function openCreateVm(project: AdminProject) { @@ -1270,7 +1272,9 @@ class="flex cursor-pointer items-center gap-2 text-xs text-foreground data-[highlighted]:bg-muted" onSelect={() => (createVmImageId = image.id)} > - {image.name} {image.version} + {[image.name, image.version, image.variant].filter(Boolean).join(' ')} {#if createVmImageId === image.id} {/if} diff --git a/apps/dashboard/src/routes/(app)/projects/[projectid]/images/+page.svelte b/apps/dashboard/src/routes/(app)/projects/[projectid]/images/+page.svelte index 71e28378..fb556e6a 100644 --- a/apps/dashboard/src/routes/(app)/projects/[projectid]/images/+page.svelte +++ b/apps/dashboard/src/routes/(app)/projects/[projectid]/images/+page.svelte @@ -22,6 +22,7 @@ isOfficial: boolean; logoSvg: string | null | undefined; name: string; + variant?: string; version: string; } @@ -183,7 +184,7 @@

{displayArchitecture(image)} - | {image.version} + | {image.version}{image.variant ? ` (${image.variant})` : ''}

diff --git a/apps/dashboard/src/routes/(app)/projects/[projectid]/servers/create/+page.svelte b/apps/dashboard/src/routes/(app)/projects/[projectid]/servers/create/+page.svelte index ba528128..88befd77 100644 --- a/apps/dashboard/src/routes/(app)/projects/[projectid]/servers/create/+page.svelte +++ b/apps/dashboard/src/routes/(app)/projects/[projectid]/servers/create/+page.svelte @@ -75,6 +75,7 @@ isOfficial: boolean; logoSvg: string | null; name: string; + variant: string; version: string; } @@ -95,6 +96,8 @@ imageType: string; logoSvg: string | null; name: string; + /** Distinct variants in admin sort order; the first one is the default. */ + variants: string[]; versions: DbImage[]; } const officialImageGroups = $derived.by(() => { @@ -108,6 +111,8 @@ } } return Array.from(groups.values(), (versions) => { + // Variant order follows the admin sort order, so the first row decides the default variant. + const variants = [...new Set(versions.map((v) => v.variant ?? ''))]; const sorted = [...versions].sort((a, b) => compareVersionsDesc(a.version, b.version)); const [representative] = sorted; return { @@ -116,6 +121,7 @@ accentColor: representative.accentColor, logoSvg: representative.logoSvg, imageType: representative.imageType, + variants, versions: sorted } satisfies ImageGroup; }); @@ -134,6 +140,7 @@ } let selectedImageId = $state(null); let selectedImageVersion = $state(null); + let selectedImageVariant = $state(''); let selectedPlanId = $state(null); type NetworkingOption = 'both' | 'ipv6'; let networkingOption = $state('both'); @@ -298,7 +305,9 @@ return officialImageGroups.filter( (g) => g.name.toLowerCase().includes(q) || - g.versions.some((v) => v.version.toLowerCase().includes(q)) + g.versions.some( + (v) => v.version.toLowerCase().includes(q) || v.variant?.toLowerCase().includes(q) + ) ); } @@ -307,11 +316,24 @@ selectedImageId = null; selectedImageVersion = null; } else { - selectedImageId = group.versions[0].id; - selectedImageVersion = group.versions[0].version; + selectImageVariant(group, group.variants[0] ?? ''); } } + function versionsForVariant(group: ImageGroup, variant: string) { + return group.versions.filter((v) => (v.variant ?? '') === variant); + } + + function selectImageVariant(group: ImageGroup, variant: string) { + const [latest] = versionsForVariant(group, variant); + if (!latest) { + return; + } + selectedImageVariant = variant; + selectedImageId = latest.id; + selectedImageVersion = latest.version; + } + function selectImageVersion(imageId: string) { const img = dbImages.find((i) => i.id === imageId); if (!img) { @@ -319,6 +341,7 @@ } selectedImageId = img.id; selectedImageVersion = img.version; + selectedImageVariant = img.variant ?? ''; } function scrollTosSection(sectionId: string) { @@ -585,6 +608,10 @@ class="mt-auto pt-2 text-xs leading-none text-muted-foreground sm:text-[10px]" > x86 | + {#if group.variants.length > 1} + {group.variants.map((v) => v || 'default').join(' / ')} + | + {/if} {group.versions.length > 1 ? `${group.versions.length} versions` : group.versions[0].version} @@ -594,13 +621,34 @@ {#if isSelected}
+ {#if group.variants.length > 1} + Variant +
+ {#each group.variants as variant (variant)} + + {/each} +
+ {/if} Version @@ -639,6 +687,7 @@ } else { selectedImageId = img.id; selectedImageVersion = img.version || null; + selectedImageVariant = img.variant ?? ''; } }} > @@ -1095,6 +1144,9 @@ Image {selectedImage?.name ?? '-'} + {#if selectedImage?.variant} + / {selectedImage.variant} + {/if} {#if selectedImageVersion} / {selectedImageVersion} {/if}