diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/policy/version-selector/CreateRuleDialog.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/policy/version-selector/CreateRuleDialog.tsx new file mode 100644 index 000000000..6cd8e4d09 --- /dev/null +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/policy/version-selector/CreateRuleDialog.tsx @@ -0,0 +1,255 @@ +"use client"; + +import type { DeploymentVersionCondition } from "@ctrlplane/validators/releases"; +import { useEffect, useState } from "react"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { toast } from "sonner"; +import { z } from "zod"; + +import { Button } from "@ctrlplane/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@ctrlplane/ui/dialog"; +import { Input } from "@ctrlplane/ui/input"; +import { Label } from "@ctrlplane/ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@ctrlplane/ui/select"; +import { + defaultCondition, + isValidDeploymentVersionCondition, +} from "@ctrlplane/validators/releases"; + +import { DeploymentVersionConditionBadge } from "~/app/[workspaceSlug]/(app)/_components/deployments/version/condition/DeploymentVersionConditionBadge"; +import { DeploymentVersionConditionDialog } from "~/app/[workspaceSlug]/(app)/_components/deployments/version/condition/DeploymentVersionConditionDialog"; +import { api } from "~/trpc/react"; + +type CreateVersionChannelRuleDialogProps = { + workspaceId: string; + open: boolean; + onOpenChange: (open: boolean) => void; +}; + +const formSchema = z.object({ + policyId: z.string().uuid("Policy selection is required"), + name: z.string().min(1, "Rule name is required"), + description: z.string().optional(), +}); +type FormData = z.infer; + +export function CreateVersionChannelRuleDialog({ + workspaceId, + open, + onOpenChange, +}: CreateVersionChannelRuleDialogProps) { + const utils = api.useUtils(); + const [currentCondition, setCurrentCondition] = + useState(defaultCondition); + + // Fetch policies for the select dropdown + const policiesQuery = api.policy.list.useQuery(workspaceId); + const eligiblePolicies = policiesQuery.data?.filter( + (p) => p.deploymentVersionSelector === null, + ); + + const { register, handleSubmit, formState, reset, watch } = useForm( + { + resolver: zodResolver(formSchema), + defaultValues: { + policyId: undefined, // No default policy selected + name: "", + description: "", + }, + }, + ); + + const selectedPolicyId = watch("policyId"); // Watch selected policy for display/logic + + const createMutation = api.policy.createDeploymentVersionSelector.useMutation( + { + onSuccess: (_, variables) => { + toast.success(`Version Selector Rule added to policy.`); + utils.policy.list.invalidate(); + utils.policy.byId.invalidate(variables.policyId); + reset(); + setCurrentCondition(defaultCondition); + onOpenChange(false); + }, + onError: (error) => { + toast.error(`Failed to add rule: ${error.message}`); + }, + }, + ); + + const onSubmit = (data: FormData) => { + if ( + !currentCondition || + !isValidDeploymentVersionCondition(currentCondition) + ) { + toast.error("A valid Version Selector condition is required."); + return; + } + createMutation.mutate({ + policyId: data.policyId, + name: data.name, + description: data.description, + deploymentVersionSelector: currentCondition, + }); + }; + + // Reset form and condition when dialog is closed/opened + // It provides consistent cleanup for all dialog closing scenarios. + // It resets the local currentCondition state, which react-hook-form doesn't manage. + useEffect(() => { + if (!open) { + reset(); + setCurrentCondition(defaultCondition); + } + }, [open, reset]); + + return ( + + + + Create Version Channel Rule + + Add a new Version Selector rule to an existing policy. + + +
+ {/* Policy Selector */} +
+ + + {formState.errors.policyId && ( +

+ {formState.errors.policyId.message} +

+ )} +
+ + {/* Rule Name */} +
+ + + {formState.errors.name && ( +

+ {formState.errors.name.message} +

+ )} +
+ + {/* Description */} +
+ + +
+ + {/* Selector Condition - Wrap Trigger Button */} +
+ +
+ {currentCondition ? ( + + ) : ( + + Default (no filter) + + )} + { + setCurrentCondition(newCondition ?? defaultCondition); + }} + deploymentId={undefined} + > + + +
+
+ + + + + +
+
+
+ ); +} diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/policy/version-selector/RuleDialog.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/policy/version-selector/RuleDialog.tsx new file mode 100644 index 000000000..774cea98f --- /dev/null +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/policy/version-selector/RuleDialog.tsx @@ -0,0 +1,203 @@ +"use client"; + +import type { RouterOutputs } from "@ctrlplane/api"; +import type { DeploymentVersionCondition } from "@ctrlplane/validators/releases"; +import { useEffect, useState } from "react"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { toast } from "sonner"; +import { z } from "zod"; + +import { Button } from "@ctrlplane/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@ctrlplane/ui/dialog"; +import { Input } from "@ctrlplane/ui/input"; +import { Label } from "@ctrlplane/ui/label"; + +import { DeploymentVersionConditionBadge } from "~/app/[workspaceSlug]/(app)/_components/deployments/version/condition/DeploymentVersionConditionBadge"; +import { DeploymentVersionConditionDialog } from "~/app/[workspaceSlug]/(app)/_components/deployments/version/condition/DeploymentVersionConditionDialog"; +import { api } from "~/trpc/react"; + +type Policy = RouterOutputs["policy"]["list"][number]; +interface PolicyWithVersionSelector extends Policy { + deploymentVersionSelector: NonNullable; +} + +const formSchema = z.object({ + name: z.string().min(1, "Rule name is required"), + description: z.string().optional(), +}); +type FormData = z.infer; + +interface VersionSelectorRuleDialogProps { + policy: PolicyWithVersionSelector; + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export function VersionSelectorRuleDialog({ + policy, + open, + onOpenChange, +}: VersionSelectorRuleDialogProps) { + const utils = api.useUtils(); + const [showConditionDialog, setShowConditionDialog] = useState(false); + + const [currentCondition, setCurrentCondition] = + useState( + policy.deploymentVersionSelector.deploymentVersionSelector, + ); + + const { register, handleSubmit, formState, reset } = useForm({ + resolver: zodResolver(formSchema), + defaultValues: { + name: policy.deploymentVersionSelector.name, + description: policy.deploymentVersionSelector.description ?? "", + }, + }); + + useEffect(() => { + if (open) { + reset({ + name: policy.deploymentVersionSelector.name, + description: policy.deploymentVersionSelector.description ?? "", + }); + setCurrentCondition( + policy.deploymentVersionSelector.deploymentVersionSelector, + ); + } + }, [policy, open, reset]); + + const updateMutation = api.policy.updateDeploymentVersionSelector.useMutation( + { + onSuccess: () => { + toast.success("Version selector rule updated"); + utils.policy.list.invalidate(); + // Consider invalidating policy.byId if used elsewhere + // utils.policy.byId.invalidate({ id: policy.id }); + onOpenChange(false); + }, + onError: (error) => { + toast.error(`Update failed: ${error.message}`); + }, + }, + ); + + // TODO: Add createMutation if needed + + const onSubmit = (data: FormData) => { + if (!currentCondition) { + toast.error("Version selector condition cannot be empty."); + return; + } + // Decide whether to create or update based on initial state? + // For now, assuming update as it's triggered from an existing rule + updateMutation.mutate({ + policyId: policy.id, + data: { + name: data.name, + description: data.description, + deploymentVersionSelector: currentCondition, + }, + }); + }; + + return ( + + + + Edit Version Selector Rule + + Update the version selector rule for policy "{policy.name}". + + +
+
+ + + {formState.errors.name && ( +

+ {formState.errors.name.message} +

+ )} +
+
+ + +
+
+ +
+ {currentCondition ? ( + + ) : ( + + No condition set + + )} + +
+
+ + + + +
+
+ + {/* Sub-Dialog for Editing the Condition */} + {showConditionDialog && ( + { + setCurrentCondition(newCondition); + setShowConditionDialog(false); + }} + deploymentId={undefined} + > + <> + + )} +
+ ); +} diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/policy/version-selector/RuleTable.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/policy/version-selector/RuleTable.tsx new file mode 100644 index 000000000..83b5824c4 --- /dev/null +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/policy/version-selector/RuleTable.tsx @@ -0,0 +1,186 @@ +"use client"; + +import type { RouterOutputs } from "@ctrlplane/api"; +import { useState } from "react"; +import Link from "next/link"; +import { IconEdit, IconTrash } from "@tabler/icons-react"; +import { useQueryClient } from "@tanstack/react-query"; +import { getQueryKey } from "@trpc/react-query"; +import { toast } from "sonner"; + +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, +} from "@ctrlplane/ui/alert-dialog"; +import { Badge } from "@ctrlplane/ui/badge"; +import { Button } from "@ctrlplane/ui/button"; +import { Card } from "@ctrlplane/ui/card"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@ctrlplane/ui/table"; + +import { VersionSelectorRuleDialog } from "~/app/[workspaceSlug]/(app)/_components/policy/version-selector/RuleDialog"; +import { api } from "~/trpc/react"; + +// Define the required Policy type with a non-null selector +type Policy = RouterOutputs["policy"]["list"][number]; +interface PolicyWithVersionSelector extends Policy { + deploymentVersionSelector: NonNullable; +} + +interface VersionSelectorRuleTableProps { + policies: PolicyWithVersionSelector[]; +} + +export function VersionSelectorRuleTable({ + policies, +}: VersionSelectorRuleTableProps) { + const queryClient = useQueryClient(); + // Adjust query key if needed based on workspaceId context if list is filtered server-side + const listPoliciesQueryKey = getQueryKey(api.policy.list); + + const [policyToDelete, setPolicyToDelete] = + useState(null); + const [policyToEdit, setPolicyToEdit] = + useState(null); + + const deleteMutation = api.policy.deleteDeploymentVersionSelector.useMutation( + { + onSuccess: (_, _variables) => { + toast.success("Version selector rule deleted successfully"); + // Consider invalidating by workspaceId if list was fetched with it + queryClient.invalidateQueries({ queryKey: listPoliciesQueryKey }); + setPolicyToDelete(null); + }, + onError: (error) => { + toast.error(`Failed to delete rule: ${error.message}`); + setPolicyToDelete(null); + }, + }, + ); + + const handleDelete = () => { + if (policyToDelete) { + deleteMutation.mutate({ policyId: policyToDelete.id }); + } + }; + + if (policies.length === 0) { + // This case should technically be handled by the parent page now, + // but include a fallback just in case. + return ( +

+ No policies with Version Selector rules found. +

+ ); + } + + return ( + !open && setPolicyToDelete(null)} + > + + + + + Policy Name + Rule Name + Description + Status + Actions + + + + {policies.map((policy) => ( + + + {/* Link to the specific policy page */} + + {policy.name} + + + {policy.deploymentVersionSelector.name} + + {policy.deploymentVersionSelector.description} + + + {policy.enabled ? ( + Active + ) : ( + Inactive + )} + + + + + + + + + ))} + +
+
+ + {/* Delete Confirmation Dialog */} + + + Are you absolutely sure? + + This action cannot be undone. This will permanently delete the + version selector rule associated with the policy " + {policyToDelete?.name}". + + + + Cancel + + + + + {/* Edit Dialog */} + {policyToEdit && ( + !open && setPolicyToEdit(null)} + /> + )} +
+ ); +} diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/policies/_components/PolicyTable.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/policies/_components/PolicyTable.tsx index 9d042cf0f..30f016c0b 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/policies/_components/PolicyTable.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/policies/_components/PolicyTable.tsx @@ -35,6 +35,7 @@ interface PolicyTableProps { const getRules = (policy: RouterOutputs["policy"]["list"][number]) => { const rules: RuleType[] = []; if (policy.denyWindows.length > 0) rules.push("deny-window"); + if (policy.deploymentVersionSelector) rules.push("version-selector"); return rules; }; diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/policies/_components/rule-themes.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/policies/_components/rule-themes.tsx index 6e125df11..341425287 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/policies/_components/rule-themes.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/policies/_components/rule-themes.tsx @@ -6,9 +6,10 @@ import { LayersIcon, LockClosedIcon, } from "@radix-ui/react-icons"; +import { IconTag } from "@tabler/icons-react"; // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents -export type RuleType = "deny-window" | string; +export type RuleType = "deny-window" | "version-selector" | string; export const getRuleTypeIcon = (type: RuleType) => { switch (type) { @@ -26,6 +27,8 @@ export const getRuleTypeIcon = (type: RuleType) => { return ; case "approval-gate": return ; + case "version-selector": + return ; default: return null; } @@ -47,6 +50,8 @@ export const getRuleTypeLabel = (type: RuleType) => { return "Release Dependency"; case "approval-gate": return "Approval Gate"; + case "version-selector": + return "Version Selector"; default: return type; } @@ -69,6 +74,8 @@ export const getTypeColorClass = (type: RuleType): string => { return "bg-rose-500/10 text-rose-400 hover:bg-rose-500/20 border-rose-500/50"; case "approval-gate": return "bg-purple-500/10 text-purple-400 hover:bg-purple-500/20 border-purple-500/50"; + case "version-selector": + return "bg-indigo-500/10 text-indigo-400 hover:bg-indigo-500/20 border-indigo-500/50"; default: return ""; } diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/policies/layout.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/policies/layout.tsx index 9e35f4573..25c0b6b4d 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/policies/layout.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/policies/layout.tsx @@ -8,6 +8,7 @@ import { IconList, IconSettings, IconSitemap, + IconTag, } from "@tabler/icons-react"; import { @@ -75,6 +76,21 @@ export default async function Layout(props: { + + Deployment Rules + + } + href={urls + .workspace(workspace.slug) + .policies() + .path("version-channels")} + > + Version Channels + + + + Rollout Control diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/policies/page.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/policies/page.tsx index a2ca3f91e..45d0d8417 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/policies/page.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/policies/page.tsx @@ -9,6 +9,7 @@ import { IconMenu2, IconPlus, IconSitemap, + IconTag, } from "@tabler/icons-react"; import { cn } from "@ctrlplane/ui"; @@ -50,6 +51,7 @@ export default async function RulesPage({ denyWindows: policies .map((p) => p.denyWindows.length) .reduce((a, b) => a + b, 0), + versionChannels: policies.filter((p) => p.deploymentVersionSelector).length, maintenance: 0, rollout: 0, successRate: 0, @@ -68,6 +70,13 @@ export default async function RulesPage({ href: `/${workspaceSlug}/policies/deny-windows`, description: "Control when deployments can occur", }, + { + title: "Version Channels", + icon: , + count: counts.versionChannels, + href: `/${workspaceSlug}/policies/version-channels`, + description: "Control which versions can be deployed", + }, { title: "Maintenance Windows", icon: , @@ -169,7 +178,7 @@ export default async function RulesPage({ - All Rules ({0}) + All Rules ({policies.length}) Active ({activePolicies.length}) diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/policies/version-channels/page.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/policies/version-channels/page.tsx new file mode 100644 index 000000000..a0d313e75 --- /dev/null +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/policies/version-channels/page.tsx @@ -0,0 +1,120 @@ +"use client"; + +import type { RouterOutputs } from "@ctrlplane/api"; +import { useState } from "react"; +import Link from "next/link"; +import { notFound } from "next/navigation"; +import { IconMenu2, IconPlus } from "@tabler/icons-react"; + +import { + Breadcrumb, + BreadcrumbItem, + BreadcrumbLink, + BreadcrumbList, + BreadcrumbPage, + BreadcrumbSeparator, +} from "@ctrlplane/ui/breadcrumb"; +import { Button } from "@ctrlplane/ui/button"; +import { Separator } from "@ctrlplane/ui/separator"; +import { SidebarTrigger } from "@ctrlplane/ui/sidebar"; +import { Skeleton } from "@ctrlplane/ui/skeleton"; + +import { api } from "~/trpc/react"; +import { PageHeader } from "../../_components/PageHeader"; +import { CreateVersionChannelRuleDialog } from "../../_components/policy/version-selector/CreateRuleDialog"; +import { VersionSelectorRuleTable } from "../../_components/policy/version-selector/RuleTable"; +import { Sidebars } from "../../../sidebars"; + +type Policy = RouterOutputs["policy"]["list"][number]; +interface PolicyWithVersionSelector extends Policy { + deploymentVersionSelector: NonNullable; +} + +function hasVersionChannel( + policy: Policy, +): policy is PolicyWithVersionSelector { + return policy.deploymentVersionSelector !== null; +} + +function VersionChannelsData({ workspaceId }: { workspaceId: string }) { + const policiesQuery = api.policy.list.useQuery(workspaceId); + + if (policiesQuery.isLoading) return ; + + if (!policiesQuery.data) + return

Error loading policies.

; + + const policiesWithVersionChannels = + policiesQuery.data.filter(hasVersionChannel); + + if (policiesWithVersionChannels.length === 0) + return ( +

+ No Version Channel rules found. Add a version selector rule to a policy + to see it here. +

+ ); + + return ; +} + +export default function VersionChannelsPage({ + params, +}: { + params: { workspaceSlug: string }; +}) { + const { workspaceSlug } = params; + const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false); + + const workspaceQuery = api.workspace.bySlug.useQuery(workspaceSlug); + + if (workspaceQuery.isLoading) return ; + + if (!workspaceQuery.data) return notFound(); + const workspace = workspaceQuery.data; + + return ( +
+ +
+ + + + + + + + + Policies + + + + + Version Channels + + + +
+
+ +
+
+
+ +
+ + +
+ ); +} diff --git a/apps/webservice/src/app/urls.ts b/apps/webservice/src/app/urls.ts index c1e4182c0..ccfb2ed12 100644 --- a/apps/webservice/src/app/urls.ts +++ b/apps/webservice/src/app/urls.ts @@ -45,6 +45,7 @@ const workspacePolicies = (slug: string) => { successCriteria: () => buildUrl(...base, "success-criteria"), dependencies: () => buildUrl(...base, "dependencies"), approvalGates: () => buildUrl(...base, "approval-gates"), + path: (subpath: string) => buildUrl(...base, subpath), }; }; diff --git a/packages/api/src/router/policy.ts b/packages/api/src/router/policy.ts index c31b51aab..08d4a8946 100644 --- a/packages/api/src/router/policy.ts +++ b/packages/api/src/router/policy.ts @@ -5,12 +5,15 @@ import { eq, takeFirst } from "@ctrlplane/db"; import { createPolicy, createPolicyRuleDenyWindow, + createPolicyRuleDeploymentVersionSelector, createPolicyTarget, policy, policyRuleDenyWindow, + policyRuleDeploymentVersionSelector, policyTarget, updatePolicy, updatePolicyRuleDenyWindow, + updatePolicyRuleDeploymentVersionSelector, updatePolicyTarget, } from "@ctrlplane/db/schema"; import { Permission } from "@ctrlplane/validators/auth"; @@ -29,7 +32,11 @@ export const policyRouter = createTRPCRouter({ .query(({ ctx, input }) => ctx.db.query.policy.findMany({ where: eq(policy.workspaceId, input), - with: { targets: true, denyWindows: true }, + with: { + targets: true, + denyWindows: true, + deploymentVersionSelector: true, + }, }), ), @@ -42,7 +49,11 @@ export const policyRouter = createTRPCRouter({ .query(async ({ ctx, input }) => ctx.db.query.policy.findFirst({ where: eq(policy.id, input), - with: { targets: true, denyWindows: true }, + with: { + targets: true, + denyWindows: true, + deploymentVersionSelector: true, + }, }), ), @@ -216,4 +227,63 @@ export const policyRouter = createTRPCRouter({ .returning() .then(takeFirst), ), + + // Deployment Version Selector endpoints + createDeploymentVersionSelector: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.PolicyCreate) + .on({ type: "policy", id: input.policyId }), + }) + .input(createPolicyRuleDeploymentVersionSelector) + .mutation(({ ctx, input }) => { + return ctx.db + .insert(policyRuleDeploymentVersionSelector) + .values(input) + .returning() + .then(takeFirst); + }), + + updateDeploymentVersionSelector: protectedProcedure + .meta({ + authorizationCheck: async ({ canUser, input }) => { + return canUser + .perform(Permission.PolicyUpdate) + .on({ type: "policy", id: input.policyId }); + }, + }) + .input( + z.object({ + policyId: z.string().uuid(), + data: updatePolicyRuleDeploymentVersionSelector.omit({ + policyId: true, + }), + }), + ) + .mutation(({ ctx, input }) => { + return ctx.db + .update(policyRuleDeploymentVersionSelector) + .set(input.data) + .where(eq(policyRuleDeploymentVersionSelector.policyId, input.policyId)) + .returning() + .then(takeFirst); + }), + + deleteDeploymentVersionSelector: protectedProcedure + .meta({ + authorizationCheck: async ({ canUser, input }) => { + return canUser + .perform(Permission.PolicyDelete) + .on({ type: "policy", id: input.policyId }); + }, + }) + .input(z.object({ policyId: z.string().uuid() })) + .mutation(({ ctx, input }) => + ctx.db + .delete(policyRuleDeploymentVersionSelector) + .where(eq(policyRuleDeploymentVersionSelector.policyId, input.policyId)) + .returning() + .then(takeFirst), + ), }); diff --git a/packages/db/drizzle/0085_demonic_union_jack.sql b/packages/db/drizzle/0085_demonic_union_jack.sql new file mode 100644 index 000000000..30d3dd091 --- /dev/null +++ b/packages/db/drizzle/0085_demonic_union_jack.sql @@ -0,0 +1,11 @@ +ALTER TABLE "policy_deployment_version_selector" RENAME TO "policy_rule_deployment_version_selector";--> statement-breakpoint +ALTER TABLE "policy_rule_deployment_version_selector" DROP CONSTRAINT "policy_deployment_version_selector_policy_id_unique";--> statement-breakpoint +ALTER TABLE "policy_rule_deployment_version_selector" DROP CONSTRAINT "policy_deployment_version_selector_policy_id_policy_id_fk"; +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "policy_rule_deployment_version_selector" ADD CONSTRAINT "policy_rule_deployment_version_selector_policy_id_policy_id_fk" FOREIGN KEY ("policy_id") REFERENCES "public"."policy"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +ALTER TABLE "policy_rule_deployment_version_selector" ADD CONSTRAINT "policy_rule_deployment_version_selector_policy_id_unique" UNIQUE("policy_id"); \ No newline at end of file diff --git a/packages/db/drizzle/meta/0085_snapshot.json b/packages/db/drizzle/meta/0085_snapshot.json new file mode 100644 index 000000000..31e0e105b --- /dev/null +++ b/packages/db/drizzle/meta/0085_snapshot.json @@ -0,0 +1,5447 @@ +{ + "id": "d02b5caa-2b8d-435c-9711-e6d1785d4f9a", + "prevId": "43adecd5-8174-4ec6-898d-33900966efb4", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "account_userId_user_id_fk": { + "name": "account_userId_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "account_provider_providerAccountId_pk": { + "name": "account_provider_providerAccountId_pk", + "columns": ["provider", "providerAccountId"] + } + }, + "uniqueConstraints": {} + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_userId_user_id_fk": { + "name": "session_userId_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "active_workspace_id": { + "name": "active_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false, + "default": "null" + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "null" + }, + "system_role": { + "name": "system_role", + "type": "system_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'user'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_active_workspace_id_workspace_id_fk": { + "name": "user_active_workspace_id_workspace_id_fk", + "tableFrom": "user", + "tableTo": "workspace", + "columnsFrom": ["active_workspace_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.user_api_key": { + "name": "user_api_key", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "key_preview": { + "name": "key_preview", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key_hash": { + "name": "key_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key_prefix": { + "name": "key_prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "user_api_key_key_prefix_key_hash_index": { + "name": "user_api_key_key_prefix_key_hash_index", + "columns": [ + { + "expression": "key_prefix", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_api_key_user_id_user_id_fk": { + "name": "user_api_key_user_id_user_id_fk", + "tableFrom": "user_api_key", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.dashboard": { + "name": "dashboard", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "dashboard_workspace_id_workspace_id_fk": { + "name": "dashboard_workspace_id_workspace_id_fk", + "tableFrom": "dashboard", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.dashboard_widget": { + "name": "dashboard_widget", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "dashboard_id": { + "name": "dashboard_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "widget": { + "name": "widget", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "x": { + "name": "x", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "y": { + "name": "y", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "w": { + "name": "w", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "h": { + "name": "h", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "dashboard_widget_dashboard_id_dashboard_id_fk": { + "name": "dashboard_widget_dashboard_id_dashboard_id_fk", + "tableFrom": "dashboard_widget", + "tableTo": "dashboard", + "columnsFrom": ["dashboard_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_variable": { + "name": "deployment_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "default_value_id": { + "name": "default_value_id", + "type": "uuid", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "schema": { + "name": "schema", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "deployment_variable_deployment_id_key_index": { + "name": "deployment_variable_deployment_id_key_index", + "columns": [ + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_variable_deployment_id_deployment_id_fk": { + "name": "deployment_variable_deployment_id_deployment_id_fk", + "tableFrom": "deployment_variable", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_variable_default_value_id_deployment_variable_value_id_fk": { + "name": "deployment_variable_default_value_id_deployment_variable_value_id_fk", + "tableFrom": "deployment_variable", + "tableTo": "deployment_variable_value", + "columnsFrom": ["default_value_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_variable_set": { + "name": "deployment_variable_set", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "variable_set_id": { + "name": "variable_set_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "deployment_variable_set_deployment_id_variable_set_id_index": { + "name": "deployment_variable_set_deployment_id_variable_set_id_index", + "columns": [ + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "variable_set_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_variable_set_deployment_id_deployment_id_fk": { + "name": "deployment_variable_set_deployment_id_deployment_id_fk", + "tableFrom": "deployment_variable_set", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_variable_set_variable_set_id_variable_set_id_fk": { + "name": "deployment_variable_set_variable_set_id_variable_set_id_fk", + "tableFrom": "deployment_variable_set", + "tableTo": "variable_set", + "columnsFrom": ["variable_set_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_variable_value": { + "name": "deployment_variable_value", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "variable_id": { + "name": "variable_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "resource_selector": { + "name": "resource_selector", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": { + "deployment_variable_value_variable_id_value_index": { + "name": "deployment_variable_value_variable_id_value_index", + "columns": [ + { + "expression": "variable_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "value", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_variable_value_variable_id_deployment_variable_id_fk": { + "name": "deployment_variable_value_variable_id_deployment_variable_id_fk", + "tableFrom": "deployment_variable_value", + "tableTo": "deployment_variable", + "columnsFrom": ["variable_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "restrict" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_version": { + "name": "deployment_version", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "deployment_version_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ready'" + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "deployment_version_deployment_id_tag_index": { + "name": "deployment_version_deployment_id_tag_index", + "columns": [ + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_version_created_at_idx": { + "name": "deployment_version_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_version_deployment_id_deployment_id_fk": { + "name": "deployment_version_deployment_id_deployment_id_fk", + "tableFrom": "deployment_version", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_version_channel": { + "name": "deployment_version_channel", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_version_selector": { + "name": "deployment_version_selector", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": { + "deployment_version_channel_deployment_id_name_index": { + "name": "deployment_version_channel_deployment_id_name_index", + "columns": [ + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_version_channel_deployment_id_deployment_id_fk": { + "name": "deployment_version_channel_deployment_id_deployment_id_fk", + "tableFrom": "deployment_version_channel", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_version_metadata": { + "name": "deployment_version_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "deployment_version_metadata_key_deployment_version_id_index": { + "name": "deployment_version_metadata_key_deployment_version_id_index", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_version_metadata_deployment_version_id_deployment_version_id_fk": { + "name": "deployment_version_metadata_deployment_version_id_deployment_version_id_fk", + "tableFrom": "deployment_version_metadata", + "tableTo": "deployment_version", + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_version_dependency": { + "name": "deployment_version_dependency", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_version_selector": { + "name": "deployment_version_selector", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": { + "deployment_version_dependency_deployment_version_id_deployment_id_index": { + "name": "deployment_version_dependency_deployment_version_id_deployment_id_index", + "columns": [ + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_version_dependency_deployment_version_id_deployment_version_id_fk": { + "name": "deployment_version_dependency_deployment_version_id_deployment_version_id_fk", + "tableFrom": "deployment_version_dependency", + "tableTo": "deployment_version", + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_version_dependency_deployment_id_deployment_id_fk": { + "name": "deployment_version_dependency_deployment_id_deployment_id_fk", + "tableFrom": "deployment_version_dependency", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment": { + "name": "deployment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "timeout": { + "name": "timeout", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "resource_selector": { + "name": "resource_selector", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": { + "deployment_system_id_slug_index": { + "name": "deployment_system_id_slug_index", + "columns": [ + { + "expression": "system_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_system_id_system_id_fk": { + "name": "deployment_system_id_system_id_fk", + "tableFrom": "deployment", + "tableTo": "system", + "columnsFrom": ["system_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployment_job_agent_id_job_agent_id_fk": { + "name": "deployment_job_agent_id_job_agent_id_fk", + "tableFrom": "deployment", + "tableTo": "job_agent", + "columnsFrom": ["job_agent_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_policy_deployment": { + "name": "environment_policy_deployment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "environment_policy_deployment_policy_id_environment_id_index": { + "name": "environment_policy_deployment_policy_id_environment_id_index", + "columns": [ + { + "expression": "policy_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_policy_deployment_policy_id_environment_policy_id_fk": { + "name": "environment_policy_deployment_policy_id_environment_policy_id_fk", + "tableFrom": "environment_policy_deployment", + "tableTo": "environment_policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_deployment_environment_id_environment_id_fk": { + "name": "environment_policy_deployment_environment_id_environment_id_fk", + "tableFrom": "environment_policy_deployment", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment": { + "name": "environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "directory": { + "name": "directory", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "resource_selector": { + "name": "resource_selector", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "environment_system_id_name_index": { + "name": "environment_system_id_name_index", + "columns": [ + { + "expression": "system_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_system_id_system_id_fk": { + "name": "environment_system_id_system_id_fk", + "tableFrom": "environment", + "tableTo": "system", + "columnsFrom": ["system_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_id_environment_policy_id_fk": { + "name": "environment_policy_id_environment_policy_id_fk", + "tableFrom": "environment", + "tableTo": "environment_policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_metadata": { + "name": "environment_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "environment_metadata_key_environment_id_index": { + "name": "environment_metadata_key_environment_id_index", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_metadata_environment_id_environment_id_fk": { + "name": "environment_metadata_environment_id_environment_id_fk", + "tableFrom": "environment_metadata", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_policy": { + "name": "environment_policy", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "approval_required": { + "name": "approval_required", + "type": "environment_policy_approval_requirement", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'automatic'" + }, + "success_status": { + "name": "success_status", + "type": "environment_policy_deployment_success_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'all'" + }, + "minimum_success": { + "name": "minimum_success", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "concurrency_limit": { + "name": "concurrency_limit", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "rollout_duration": { + "name": "rollout_duration", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "minimum_release_interval": { + "name": "minimum_release_interval", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "release_sequencing": { + "name": "release_sequencing", + "type": "release_sequencing_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'cancel'" + } + }, + "indexes": {}, + "foreignKeys": { + "environment_policy_system_id_system_id_fk": { + "name": "environment_policy_system_id_system_id_fk", + "tableFrom": "environment_policy", + "tableTo": "system", + "columnsFrom": ["system_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_environment_id_environment_id_fk": { + "name": "environment_policy_environment_id_environment_id_fk", + "tableFrom": "environment_policy", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_policy_approval": { + "name": "environment_policy_approval", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "approval_status_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "approved_at": { + "name": "approved_at", + "type": "timestamp (0) with time zone", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": { + "environment_policy_approval_policy_id_release_id_index": { + "name": "environment_policy_approval_policy_id_release_id_index", + "columns": [ + { + "expression": "policy_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "release_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_policy_approval_policy_id_environment_policy_id_fk": { + "name": "environment_policy_approval_policy_id_environment_policy_id_fk", + "tableFrom": "environment_policy_approval", + "tableTo": "environment_policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_approval_release_id_deployment_version_id_fk": { + "name": "environment_policy_approval_release_id_deployment_version_id_fk", + "tableFrom": "environment_policy_approval", + "tableTo": "deployment_version", + "columnsFrom": ["release_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_approval_user_id_user_id_fk": { + "name": "environment_policy_approval_user_id_user_id_fk", + "tableFrom": "environment_policy_approval", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_policy_release_window": { + "name": "environment_policy_release_window", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "start_time": { + "name": "start_time", + "type": "timestamp (0) with time zone", + "primaryKey": false, + "notNull": true + }, + "end_time": { + "name": "end_time", + "type": "timestamp (0) with time zone", + "primaryKey": false, + "notNull": true + }, + "recurrence": { + "name": "recurrence", + "type": "recurrence_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "environment_policy_release_window_policy_id_environment_policy_id_fk": { + "name": "environment_policy_release_window_policy_id_environment_policy_id_fk", + "tableFrom": "environment_policy_release_window", + "tableTo": "environment_policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.event": { + "name": "event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.hook": { + "name": "hook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scope_type": { + "name": "scope_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scope_id": { + "name": "scope_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.runhook": { + "name": "runhook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hook_id": { + "name": "hook_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "runbook_id": { + "name": "runbook_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "runhook_hook_id_runbook_id_index": { + "name": "runhook_hook_id_runbook_id_index", + "columns": [ + { + "expression": "hook_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "runbook_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "runhook_hook_id_hook_id_fk": { + "name": "runhook_hook_id_hook_id_fk", + "tableFrom": "runhook", + "tableTo": "hook", + "columnsFrom": ["hook_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "runhook_runbook_id_runbook_id_fk": { + "name": "runhook_runbook_id_runbook_id_fk", + "tableFrom": "runhook", + "tableTo": "runbook", + "columnsFrom": ["runbook_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.github_entity": { + "name": "github_entity", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "installation_id": { + "name": "installation_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "github_entity_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'organization'" + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "added_by_user_id": { + "name": "added_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "avatar_url": { + "name": "avatar_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "unique_installation_workspace": { + "name": "unique_installation_workspace", + "columns": [ + { + "expression": "installation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "github_entity_added_by_user_id_user_id_fk": { + "name": "github_entity_added_by_user_id_user_id_fk", + "tableFrom": "github_entity", + "tableTo": "user", + "columnsFrom": ["added_by_user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "github_entity_workspace_id_workspace_id_fk": { + "name": "github_entity_workspace_id_workspace_id_fk", + "tableFrom": "github_entity", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.github_user": { + "name": "github_user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "github_user_id": { + "name": "github_user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "github_username": { + "name": "github_username", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "github_user_user_id_user_id_fk": { + "name": "github_user_user_id_user_id_fk", + "tableFrom": "github_user", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job_resource_relationship": { + "name": "job_resource_relationship", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "resource_identifier": { + "name": "resource_identifier", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "job_resource_relationship_job_id_resource_identifier_index": { + "name": "job_resource_relationship_job_id_resource_identifier_index", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_resource_relationship_job_id_job_id_fk": { + "name": "job_resource_relationship_job_id_job_id_fk", + "tableFrom": "job_resource_relationship", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource": { + "name": "resource", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "locked_at": { + "name": "locked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "resource_identifier_workspace_id_index": { + "name": "resource_identifier_workspace_id_index", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_provider_id_resource_provider_id_fk": { + "name": "resource_provider_id_resource_provider_id_fk", + "tableFrom": "resource", + "tableTo": "resource_provider", + "columnsFrom": ["provider_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "resource_workspace_id_workspace_id_fk": { + "name": "resource_workspace_id_workspace_id_fk", + "tableFrom": "resource", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_metadata": { + "name": "resource_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "resource_metadata_key_resource_id_index": { + "name": "resource_metadata_key_resource_id_index", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_metadata_resource_id_resource_id_fk": { + "name": "resource_metadata_resource_id_resource_id_fk", + "tableFrom": "resource_metadata", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_relationship": { + "name": "resource_relationship", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "from_identifier": { + "name": "from_identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "to_identifier": { + "name": "to_identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "resource_relationship_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "resource_relationship_to_identifier_from_identifier_index": { + "name": "resource_relationship_to_identifier_from_identifier_index", + "columns": [ + { + "expression": "to_identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "from_identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_relationship_workspace_id_workspace_id_fk": { + "name": "resource_relationship_workspace_id_workspace_id_fk", + "tableFrom": "resource_relationship", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_schema": { + "name": "resource_schema", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "json_schema": { + "name": "json_schema", + "type": "json", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "resource_schema_version_kind_workspace_id_index": { + "name": "resource_schema_version_kind_workspace_id_index", + "columns": [ + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_schema_workspace_id_workspace_id_fk": { + "name": "resource_schema_workspace_id_workspace_id_fk", + "tableFrom": "resource_schema", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_variable": { + "name": "resource_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "sensitive": { + "name": "sensitive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "resource_variable_resource_id_key_index": { + "name": "resource_variable_resource_id_key_index", + "columns": [ + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_variable_resource_id_resource_id_fk": { + "name": "resource_variable_resource_id_resource_id_fk", + "tableFrom": "resource_variable", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_view": { + "name": "resource_view", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "filter": { + "name": "filter", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "resource_view_workspace_id_workspace_id_fk": { + "name": "resource_view_workspace_id_workspace_id_fk", + "tableFrom": "resource_view", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.azure_tenant": { + "name": "azure_tenant", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "azure_tenant_tenant_id_index": { + "name": "azure_tenant_tenant_id_index", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "azure_tenant_workspace_id_workspace_id_fk": { + "name": "azure_tenant_workspace_id_workspace_id_fk", + "tableFrom": "azure_tenant", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_provider": { + "name": "resource_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "resource_provider_workspace_id_name_index": { + "name": "resource_provider_workspace_id_name_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_provider_workspace_id_workspace_id_fk": { + "name": "resource_provider_workspace_id_workspace_id_fk", + "tableFrom": "resource_provider", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_provider_aws": { + "name": "resource_provider_aws", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_provider_id": { + "name": "resource_provider_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "aws_role_arns": { + "name": "aws_role_arns", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "import_eks": { + "name": "import_eks", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "import_vpc": { + "name": "import_vpc", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "resource_provider_aws_resource_provider_id_resource_provider_id_fk": { + "name": "resource_provider_aws_resource_provider_id_resource_provider_id_fk", + "tableFrom": "resource_provider_aws", + "tableTo": "resource_provider", + "columnsFrom": ["resource_provider_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_provider_azure": { + "name": "resource_provider_azure", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_provider_id": { + "name": "resource_provider_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "resource_provider_azure_resource_provider_id_resource_provider_id_fk": { + "name": "resource_provider_azure_resource_provider_id_resource_provider_id_fk", + "tableFrom": "resource_provider_azure", + "tableTo": "resource_provider", + "columnsFrom": ["resource_provider_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "resource_provider_azure_tenant_id_azure_tenant_id_fk": { + "name": "resource_provider_azure_tenant_id_azure_tenant_id_fk", + "tableFrom": "resource_provider_azure", + "tableTo": "azure_tenant", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_provider_google": { + "name": "resource_provider_google", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_provider_id": { + "name": "resource_provider_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_ids": { + "name": "project_ids", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "import_gke": { + "name": "import_gke", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "import_namespaces": { + "name": "import_namespaces", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "import_vcluster": { + "name": "import_vcluster", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "import_vms": { + "name": "import_vms", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "import_vpc": { + "name": "import_vpc", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "resource_provider_google_resource_provider_id_resource_provider_id_fk": { + "name": "resource_provider_google_resource_provider_id_resource_provider_id_fk", + "tableFrom": "resource_provider_google", + "tableTo": "resource_provider", + "columnsFrom": ["resource_provider_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.system": { + "name": "system", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "system_workspace_id_slug_index": { + "name": "system_workspace_id_slug_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "system_workspace_id_workspace_id_fk": { + "name": "system_workspace_id_workspace_id_fk", + "tableFrom": "system", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.runbook": { + "name": "runbook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": { + "runbook_system_id_system_id_fk": { + "name": "runbook_system_id_system_id_fk", + "tableFrom": "runbook", + "tableTo": "system", + "columnsFrom": ["system_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "runbook_job_agent_id_job_agent_id_fk": { + "name": "runbook_job_agent_id_job_agent_id_fk", + "tableFrom": "runbook", + "tableTo": "job_agent", + "columnsFrom": ["job_agent_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.runbook_job_trigger": { + "name": "runbook_job_trigger", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "runbook_id": { + "name": "runbook_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "runbook_job_trigger_job_id_job_id_fk": { + "name": "runbook_job_trigger_job_id_job_id_fk", + "tableFrom": "runbook_job_trigger", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "runbook_job_trigger_runbook_id_runbook_id_fk": { + "name": "runbook_job_trigger_runbook_id_runbook_id_fk", + "tableFrom": "runbook_job_trigger", + "tableTo": "runbook", + "columnsFrom": ["runbook_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "runbook_job_trigger_job_id_unique": { + "name": "runbook_job_trigger_job_id_unique", + "nullsNotDistinct": false, + "columns": ["job_id"] + } + } + }, + "public.team": { + "name": "team", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "team_workspace_id_workspace_id_fk": { + "name": "team_workspace_id_workspace_id_fk", + "tableFrom": "team", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.team_member": { + "name": "team_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "team_member_team_id_user_id_index": { + "name": "team_member_team_id_user_id_index", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "team_member_team_id_team_id_fk": { + "name": "team_member_team_id_team_id_fk", + "tableFrom": "team_member", + "tableTo": "team", + "columnsFrom": ["team_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "team_member_user_id_user_id_fk": { + "name": "team_member_user_id_user_id_fk", + "tableFrom": "team_member", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job": { + "name": "job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "job_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "job_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'policy_passing'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "job_created_at_idx": { + "name": "job_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_status_idx": { + "name": "job_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_job_agent_id_job_agent_id_fk": { + "name": "job_job_agent_id_job_agent_id_fk", + "tableFrom": "job", + "tableTo": "job_agent", + "columnsFrom": ["job_agent_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job_metadata": { + "name": "job_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "job_metadata_key_job_id_index": { + "name": "job_metadata_key_job_id_index", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_metadata_job_id_job_id_fk": { + "name": "job_metadata_job_id_job_id_fk", + "tableFrom": "job_metadata", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job_variable": { + "name": "job_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "sensitive": { + "name": "sensitive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "job_variable_job_id_key_index": { + "name": "job_variable_job_id_key_index", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_variable_job_id_job_id_fk": { + "name": "job_variable_job_id_job_id_fk", + "tableFrom": "job_variable", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.workspace": { + "name": "workspace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "google_service_account_email": { + "name": "google_service_account_email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "aws_role_arn": { + "name": "aws_role_arn", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_slug_unique": { + "name": "workspace_slug_unique", + "nullsNotDistinct": false, + "columns": ["slug"] + } + } + }, + "public.workspace_email_domain_matching": { + "name": "workspace_email_domain_matching", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "verification_code": { + "name": "verification_code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "verification_email": { + "name": "verification_email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_email_domain_matching_workspace_id_domain_index": { + "name": "workspace_email_domain_matching_workspace_id_domain_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_email_domain_matching_workspace_id_workspace_id_fk": { + "name": "workspace_email_domain_matching_workspace_id_workspace_id_fk", + "tableFrom": "workspace_email_domain_matching", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_email_domain_matching_role_id_role_id_fk": { + "name": "workspace_email_domain_matching_role_id_role_id_fk", + "tableFrom": "workspace_email_domain_matching", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.variable_set": { + "name": "variable_set", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "variable_set_system_id_system_id_fk": { + "name": "variable_set_system_id_system_id_fk", + "tableFrom": "variable_set", + "tableTo": "system", + "columnsFrom": ["system_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.variable_set_environment": { + "name": "variable_set_environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "variable_set_id": { + "name": "variable_set_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "variable_set_environment_variable_set_id_variable_set_id_fk": { + "name": "variable_set_environment_variable_set_id_variable_set_id_fk", + "tableFrom": "variable_set_environment", + "tableTo": "variable_set", + "columnsFrom": ["variable_set_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "variable_set_environment_environment_id_environment_id_fk": { + "name": "variable_set_environment_environment_id_environment_id_fk", + "tableFrom": "variable_set_environment", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.variable_set_value": { + "name": "variable_set_value", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "variable_set_id": { + "name": "variable_set_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "variable_set_value_variable_set_id_key_index": { + "name": "variable_set_value_variable_set_id_key_index", + "columns": [ + { + "expression": "variable_set_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "variable_set_value_variable_set_id_variable_set_id_fk": { + "name": "variable_set_value_variable_set_id_variable_set_id_fk", + "tableFrom": "variable_set_value", + "tableTo": "variable_set", + "columnsFrom": ["variable_set_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.workspace_invite_token": { + "name": "workspace_invite_token", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "gen_random_uuid()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_invite_token_role_id_role_id_fk": { + "name": "workspace_invite_token_role_id_role_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invite_token_workspace_id_workspace_id_fk": { + "name": "workspace_invite_token_workspace_id_workspace_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invite_token_created_by_user_id_fk": { + "name": "workspace_invite_token_created_by_user_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_invite_token_token_unique": { + "name": "workspace_invite_token_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + } + }, + "public.resource_metadata_group": { + "name": "resource_metadata_group", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "keys": { + "name": "keys", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "include_null_combinations": { + "name": "include_null_combinations", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "resource_metadata_group_workspace_id_workspace_id_fk": { + "name": "resource_metadata_group_workspace_id_workspace_id_fk", + "tableFrom": "resource_metadata_group", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.runbook_variable": { + "name": "runbook_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "runbook_id": { + "name": "runbook_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "schema": { + "name": "schema", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "runbook_variable_runbook_id_key_index": { + "name": "runbook_variable_runbook_id_key_index", + "columns": [ + { + "expression": "runbook_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "runbook_variable_runbook_id_runbook_id_fk": { + "name": "runbook_variable_runbook_id_runbook_id_fk", + "tableFrom": "runbook_variable", + "tableTo": "runbook", + "columnsFrom": ["runbook_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.entity_role": { + "name": "entity_role", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "entity_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scope_id": { + "name": "scope_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scope_type": { + "name": "scope_type", + "type": "scope_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "entity_role_role_id_entity_type_entity_id_scope_id_scope_type_index": { + "name": "entity_role_role_id_entity_type_entity_id_scope_id_scope_type_index", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "entity_role_role_id_role_id_fk": { + "name": "entity_role_role_id_role_id_fk", + "tableFrom": "entity_role", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.role": { + "name": "role", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "role_workspace_id_workspace_id_fk": { + "name": "role_workspace_id_workspace_id_fk", + "tableFrom": "role", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.role_permission": { + "name": "role_permission", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "permission": { + "name": "permission", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "role_permission_role_id_permission_index": { + "name": "role_permission_role_id_permission_index", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "role_permission_role_id_role_id_fk": { + "name": "role_permission_role_id_role_id_fk", + "tableFrom": "role_permission", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job_agent": { + "name": "job_agent", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": { + "job_agent_workspace_id_name_index": { + "name": "job_agent_workspace_id_name_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_agent_workspace_id_workspace_id_fk": { + "name": "job_agent_workspace_id_workspace_id_fk", + "tableFrom": "job_agent", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_policy_deployment_version_channel": { + "name": "environment_policy_deployment_version_channel", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "environment_policy_deployment_version_channel_policy_id_channel_id_index": { + "name": "environment_policy_deployment_version_channel_policy_id_channel_id_index", + "columns": [ + { + "expression": "policy_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "environment_policy_deployment_version_channel_policy_id_deployment_id_index": { + "name": "environment_policy_deployment_version_channel_policy_id_deployment_id_index", + "columns": [ + { + "expression": "policy_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_policy_deployment_version_channel_policy_id_environment_policy_id_fk": { + "name": "environment_policy_deployment_version_channel_policy_id_environment_policy_id_fk", + "tableFrom": "environment_policy_deployment_version_channel", + "tableTo": "environment_policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_deployment_version_channel_channel_id_deployment_version_channel_id_fk": { + "name": "environment_policy_deployment_version_channel_channel_id_deployment_version_channel_id_fk", + "tableFrom": "environment_policy_deployment_version_channel", + "tableTo": "deployment_version_channel", + "columnsFrom": ["channel_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_deployment_version_channel_deployment_id_deployment_id_fk": { + "name": "environment_policy_deployment_version_channel_deployment_id_deployment_id_fk", + "tableFrom": "environment_policy_deployment_version_channel", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.release_job_trigger": { + "name": "release_job_trigger", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "release_job_trigger_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "caused_by_id": { + "name": "caused_by_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "release_job_trigger_job_id_job_id_fk": { + "name": "release_job_trigger_job_id_job_id_fk", + "tableFrom": "release_job_trigger", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "release_job_trigger_caused_by_id_user_id_fk": { + "name": "release_job_trigger_caused_by_id_user_id_fk", + "tableFrom": "release_job_trigger", + "tableTo": "user", + "columnsFrom": ["caused_by_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "release_job_trigger_deployment_version_id_deployment_version_id_fk": { + "name": "release_job_trigger_deployment_version_id_deployment_version_id_fk", + "tableFrom": "release_job_trigger", + "tableTo": "deployment_version", + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_job_trigger_resource_id_resource_id_fk": { + "name": "release_job_trigger_resource_id_resource_id_fk", + "tableFrom": "release_job_trigger", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_job_trigger_environment_id_environment_id_fk": { + "name": "release_job_trigger_environment_id_environment_id_fk", + "tableFrom": "release_job_trigger", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "release_job_trigger_job_id_unique": { + "name": "release_job_trigger_job_id_unique", + "nullsNotDistinct": false, + "columns": ["job_id"] + } + } + }, + "public.policy": { + "name": "policy", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "priority": { + "name": "priority", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_workspace_id_workspace_id_fk": { + "name": "policy_workspace_id_workspace_id_fk", + "tableFrom": "policy", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.policy_rule_deployment_version_selector": { + "name": "policy_rule_deployment_version_selector", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "deployment_version_selector": { + "name": "deployment_version_selector", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_deployment_version_selector_policy_id_policy_id_fk": { + "name": "policy_rule_deployment_version_selector_policy_id_policy_id_fk", + "tableFrom": "policy_rule_deployment_version_selector", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "policy_rule_deployment_version_selector_policy_id_unique": { + "name": "policy_rule_deployment_version_selector_policy_id_unique", + "nullsNotDistinct": false, + "columns": ["policy_id"] + } + } + }, + "public.policy_target": { + "name": "policy_target", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_selector": { + "name": "deployment_selector", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "environment_selector": { + "name": "environment_selector", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_target_policy_id_policy_id_fk": { + "name": "policy_target_policy_id_policy_id_fk", + "tableFrom": "policy_target", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.release": { + "name": "release", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "release_target_id": { + "name": "release_target_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "version_id": { + "name": "version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "release_release_target_id_release_target_id_fk": { + "name": "release_release_target_id_release_target_id_fk", + "tableFrom": "release", + "tableTo": "release_target", + "columnsFrom": ["release_target_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_version_id_deployment_version_id_fk": { + "name": "release_version_id_deployment_version_id_fk", + "tableFrom": "release", + "tableTo": "deployment_version", + "columnsFrom": ["version_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.release_job": { + "name": "release_job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "release_job_release_id_release_id_fk": { + "name": "release_job_release_id_release_id_fk", + "tableFrom": "release_job", + "tableTo": "release", + "columnsFrom": ["release_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_job_job_id_job_id_fk": { + "name": "release_job_job_id_job_id_fk", + "tableFrom": "release_job", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.release_target": { + "name": "release_target", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "desired_release_id": { + "name": "desired_release_id", + "type": "uuid", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": { + "release_target_resource_id_environment_id_deployment_id_index": { + "name": "release_target_resource_id_environment_id_deployment_id_index", + "columns": [ + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "release_target_resource_id_resource_id_fk": { + "name": "release_target_resource_id_resource_id_fk", + "tableFrom": "release_target", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_target_environment_id_environment_id_fk": { + "name": "release_target_environment_id_environment_id_fk", + "tableFrom": "release_target", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_target_deployment_id_deployment_id_fk": { + "name": "release_target_deployment_id_deployment_id_fk", + "tableFrom": "release_target", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_target_desired_release_id_release_id_fk": { + "name": "release_target_desired_release_id_release_id_fk", + "tableFrom": "release_target", + "tableTo": "release", + "columnsFrom": ["desired_release_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.release_variable": { + "name": "release_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "sensitive": { + "name": "sensitive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "release_variable_release_id_key_index": { + "name": "release_variable_release_id_key_index", + "columns": [ + { + "expression": "release_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "release_variable_release_id_release_id_fk": { + "name": "release_variable_release_id_release_id_fk", + "tableFrom": "release_variable", + "tableTo": "release", + "columnsFrom": ["release_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.policy_rule_deny_window": { + "name": "policy_rule_deny_window", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "rrule": { + "name": "rrule", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "dtend": { + "name": "dtend", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "time_zone": { + "name": "time_zone", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_deny_window_policy_id_policy_id_fk": { + "name": "policy_rule_deny_window_policy_id_policy_id_fk", + "tableFrom": "policy_rule_deny_window", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.policy_rule_user_approval": { + "name": "policy_rule_user_approval", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_user_approval_policy_id_policy_id_fk": { + "name": "policy_rule_user_approval_policy_id_policy_id_fk", + "tableFrom": "policy_rule_user_approval", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "policy_rule_user_approval_user_id_user_id_fk": { + "name": "policy_rule_user_approval_user_id_user_id_fk", + "tableFrom": "policy_rule_user_approval", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.policy_rule_user_approval_record": { + "name": "policy_rule_user_approval_record", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "approval_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "approved_at": { + "name": "approved_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "rule_id": { + "name": "rule_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_user_approval_record_user_id_user_id_fk": { + "name": "policy_rule_user_approval_record_user_id_user_id_fk", + "tableFrom": "policy_rule_user_approval_record", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "policy_rule_user_approval_record_rule_id_policy_rule_user_approval_id_fk": { + "name": "policy_rule_user_approval_record_rule_id_policy_rule_user_approval_id_fk", + "tableFrom": "policy_rule_user_approval_record", + "tableTo": "policy_rule_user_approval", + "columnsFrom": ["rule_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.policy_rule_role_approval": { + "name": "policy_rule_role_approval", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "required_approvals_count": { + "name": "required_approvals_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_role_approval_policy_id_policy_id_fk": { + "name": "policy_rule_role_approval_policy_id_policy_id_fk", + "tableFrom": "policy_rule_role_approval", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "policy_rule_role_approval_role_id_role_id_fk": { + "name": "policy_rule_role_approval_role_id_role_id_fk", + "tableFrom": "policy_rule_role_approval", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.policy_rule_role_approval_record": { + "name": "policy_rule_role_approval_record", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "approval_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "approved_at": { + "name": "approved_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "rule_id": { + "name": "rule_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_role_approval_record_user_id_user_id_fk": { + "name": "policy_rule_role_approval_record_user_id_user_id_fk", + "tableFrom": "policy_rule_role_approval_record", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "policy_rule_role_approval_record_rule_id_policy_rule_role_approval_id_fk": { + "name": "policy_rule_role_approval_record_rule_id_policy_rule_role_approval_id_fk", + "tableFrom": "policy_rule_role_approval_record", + "tableTo": "policy_rule_role_approval", + "columnsFrom": ["rule_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.policy_rule_any_approval": { + "name": "policy_rule_any_approval", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "required_approvals_count": { + "name": "required_approvals_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_any_approval_policy_id_policy_id_fk": { + "name": "policy_rule_any_approval_policy_id_policy_id_fk", + "tableFrom": "policy_rule_any_approval", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.policy_rule_any_approval_record": { + "name": "policy_rule_any_approval_record", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "approval_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "approved_at": { + "name": "approved_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "unique_rule_id_user_id": { + "name": "unique_rule_id_user_id", + "columns": [ + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "policy_rule_any_approval_record_user_id_user_id_fk": { + "name": "policy_rule_any_approval_record_user_id_user_id_fk", + "tableFrom": "policy_rule_any_approval_record", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "public.system_role": { + "name": "system_role", + "schema": "public", + "values": ["user", "admin"] + }, + "public.deployment_version_status": { + "name": "deployment_version_status", + "schema": "public", + "values": ["building", "ready", "failed"] + }, + "public.environment_policy_approval_requirement": { + "name": "environment_policy_approval_requirement", + "schema": "public", + "values": ["manual", "automatic"] + }, + "public.approval_status_type": { + "name": "approval_status_type", + "schema": "public", + "values": ["pending", "approved", "rejected"] + }, + "public.environment_policy_deployment_success_type": { + "name": "environment_policy_deployment_success_type", + "schema": "public", + "values": ["all", "some", "optional"] + }, + "public.recurrence_type": { + "name": "recurrence_type", + "schema": "public", + "values": ["hourly", "daily", "weekly", "monthly"] + }, + "public.release_sequencing_type": { + "name": "release_sequencing_type", + "schema": "public", + "values": ["wait", "cancel"] + }, + "public.github_entity_type": { + "name": "github_entity_type", + "schema": "public", + "values": ["organization", "user"] + }, + "public.resource_relationship_type": { + "name": "resource_relationship_type", + "schema": "public", + "values": ["associated_with", "depends_on"] + }, + "public.job_reason": { + "name": "job_reason", + "schema": "public", + "values": [ + "policy_passing", + "policy_override", + "env_policy_override", + "config_policy_override" + ] + }, + "public.job_status": { + "name": "job_status", + "schema": "public", + "values": [ + "cancelled", + "skipped", + "in_progress", + "action_required", + "pending", + "failure", + "invalid_job_agent", + "invalid_integration", + "external_run_not_found", + "successful" + ] + }, + "public.entity_type": { + "name": "entity_type", + "schema": "public", + "values": ["user", "team"] + }, + "public.scope_type": { + "name": "scope_type", + "schema": "public", + "values": [ + "deploymentVersion", + "deploymentVersionChannel", + "resource", + "resourceProvider", + "resourceMetadataGroup", + "workspace", + "environment", + "environmentPolicy", + "deploymentVariable", + "variableSet", + "system", + "deployment", + "job", + "jobAgent", + "runbook", + "policy", + "resourceView" + ] + }, + "public.release_job_trigger_type": { + "name": "release_job_trigger_type", + "schema": "public", + "values": [ + "new_version", + "version_updated", + "new_resource", + "resource_changed", + "api", + "redeploy", + "force_deploy", + "new_environment", + "variable_changed", + "retry" + ] + }, + "public.approval_status": { + "name": "approval_status", + "schema": "public", + "values": ["approved", "rejected"] + } + }, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index 3887dc713..22ddeb73b 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -596,6 +596,13 @@ "when": 1743976930686, "tag": "0084_abnormal_lady_ursula", "breakpoints": true + }, + { + "idx": 85, + "version": "7", + "when": 1744074724106, + "tag": "0085_demonic_union_jack", + "breakpoints": true } ] } diff --git a/packages/db/src/schema/policy-relations.ts b/packages/db/src/schema/policy-relations.ts index 2917721bd..65fd8712f 100644 --- a/packages/db/src/schema/policy-relations.ts +++ b/packages/db/src/schema/policy-relations.ts @@ -2,7 +2,7 @@ import { relations } from "drizzle-orm"; import { policy, - policyDeploymentVersionSelector, + policyRuleDeploymentVersionSelector, policyTarget, } from "./policy.js"; import { @@ -23,10 +23,7 @@ export const policyRelations = relations(policy, ({ many, one }) => ({ }), targets: many(policyTarget), denyWindows: many(policyRuleDenyWindow), - deploymentVersionSelector: one(policyDeploymentVersionSelector, { - fields: [policy.id], - references: [policyDeploymentVersionSelector.policyId], - }), + deploymentVersionSelector: one(policyRuleDeploymentVersionSelector), versionUserApprovals: many(policyRuleUserApproval), versionRoleApprovals: many(policyRuleRoleApproval), @@ -39,3 +36,13 @@ export const policyTargetRelations = relations(policyTarget, ({ one }) => ({ references: [policy.id], }), })); + +export const policyRuleDeploymentVersionSelectorRelations = relations( + policyRuleDeploymentVersionSelector, + ({ one }) => ({ + policy: one(policy, { + fields: [policyRuleDeploymentVersionSelector.policyId], + references: [policy.id], + }), + }), +); diff --git a/packages/db/src/schema/policy.ts b/packages/db/src/schema/policy.ts index 8b05bf4fc..b26bcb022 100644 --- a/packages/db/src/schema/policy.ts +++ b/packages/db/src/schema/policy.ts @@ -17,6 +17,7 @@ import { z } from "zod"; import { deploymentCondition } from "@ctrlplane/validators/deployments"; import { environmentCondition } from "@ctrlplane/validators/environments"; +import { deploymentVersionCondition } from "@ctrlplane/validators/releases"; import { workspace } from "./workspace.js"; @@ -51,8 +52,8 @@ export const policyTarget = pgTable("policy_target", { .$type(), }); -export const policyDeploymentVersionSelector = pgTable( - "policy_deployment_version_selector", +export const policyRuleDeploymentVersionSelector = pgTable( + "policy_rule_deployment_version_selector", { id: uuid("id").primaryKey().defaultRandom(), @@ -87,6 +88,16 @@ const policyTargetInsertSchema = createInsertSchema(policyTarget, { environmentSelector: environmentCondition.nullable(), }).omit({ id: true }); +const policyRuleDeploymentVersionSelectorInsertSchema = createInsertSchema( + policyRuleDeploymentVersionSelector, + { + policyId: z.string().uuid(), + name: z.string().min(1, "Rule name is required"), + description: z.string().optional(), + deploymentVersionSelector: deploymentVersionCondition, + }, +).omit({ id: true }); + // Export schemas and types export const createPolicy = policyInsertSchema; export type CreatePolicy = z.infer; @@ -100,9 +111,21 @@ export type CreatePolicyTarget = z.infer; export const updatePolicyTarget = policyTargetInsertSchema.partial(); export type UpdatePolicyTarget = z.infer; +export const createPolicyRuleDeploymentVersionSelector = + policyRuleDeploymentVersionSelectorInsertSchema; +export type CreatePolicyRuleDeploymentVersionSelector = z.infer< + typeof createPolicyRuleDeploymentVersionSelector +>; + +export const updatePolicyRuleDeploymentVersionSelector = + policyRuleDeploymentVersionSelectorInsertSchema.partial(); +export type UpdatePolicyRuleDeploymentVersionSelector = z.infer< + typeof updatePolicyRuleDeploymentVersionSelector +>; + // Export policy types export type Policy = InferSelectModel; export type PolicyTarget = InferSelectModel; -export type PolicyDeploymentVersionSelector = InferSelectModel< - typeof policyDeploymentVersionSelector +export type PolicyRuleDeploymentVersionSelector = InferSelectModel< + typeof policyRuleDeploymentVersionSelector >; diff --git a/packages/job-dispatch/src/job-dispatch.ts b/packages/job-dispatch/src/job-dispatch.ts index 0d49b48e7..5daa95159 100644 --- a/packages/job-dispatch/src/job-dispatch.ts +++ b/packages/job-dispatch/src/job-dispatch.ts @@ -99,6 +99,7 @@ class DispatchBuilder { data: { jobId: wf.id }, })), ); + await Promise.all( validJobsWithResolvedVariables.map((j) => updateJob(this.db, j.id, { status: JobStatus.InProgress }), diff --git a/packages/rule-engine/src/evaluate.ts b/packages/rule-engine/src/evaluate.ts index 43394ed16..c64442568 100644 --- a/packages/rule-engine/src/evaluate.ts +++ b/packages/rule-engine/src/evaluate.ts @@ -6,6 +6,10 @@ import type { Policy } from "./types.js"; import { Releases } from "./releases.js"; import { RuleEngine } from "./rule-engine.js"; import { DeploymentDenyRule } from "./rules/deployment-deny-rule.js"; +import { + DeploymentVersionSelectorRule, + getApplicableVersionIds, +} from "./rules/deployment-version-selector-rule.js"; import { getAnyApprovalRecords, getRoleApprovalRecords, @@ -25,6 +29,15 @@ const denyWindows = (policy: Policy | null) => }), ); +const versionSelector = (policy: Policy | null) => + policy == null + ? [] + : [ + new DeploymentVersionSelectorRule( + getApplicableVersionIds(policy.deploymentVersionSelector), + ), + ]; + const versionAnyApprovalRule = ( approvalRules?: Policy["versionAnyApprovals"] | null, ) => { @@ -130,6 +143,7 @@ export const evaluateRepository = async ( const policy = await repository.getPolicy(); const rules = [ ...denyWindows(policy), + ...versionSelector(policy), ...versionUserApprovalRule(policy?.versionUserApprovals), ...versionAnyApprovalRule(policy?.versionAnyApprovals), ...versionRoleApprovalRule(policy?.versionRoleApprovals), diff --git a/packages/rule-engine/src/rules/__tests__/deployment-version-selector-rule.test.ts b/packages/rule-engine/src/rules/__tests__/deployment-version-selector-rule.test.ts new file mode 100644 index 000000000..e063a38b0 --- /dev/null +++ b/packages/rule-engine/src/rules/__tests__/deployment-version-selector-rule.test.ts @@ -0,0 +1,132 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +import type { + DeploymentResourceContext, + Policy, + ResolvedRelease, +} from "../../types.js"; +import { Releases } from "../../releases.js"; +import { + DeploymentVersionSelectorRule, + getApplicableVersionIds, +} from "../deployment-version-selector-rule.js"; + +describe("DeploymentVersionSelectorRule", () => { + let releases: Releases; + let context: DeploymentResourceContext; + + beforeEach(() => { + // Create a sample set of releases + const sampleReleases: ResolvedRelease[] = [ + { + id: "rel-1", + createdAt: new Date("2023-01-01T12:00:00Z"), + version: { + id: "ver-1", + tag: "v1.0.0", + config: {}, + metadata: { environment: "prod" }, + }, + variables: {}, + }, + { + id: "rel-2", + createdAt: new Date("2023-01-02T12:00:00Z"), + version: { + id: "ver-2", + tag: "v1.1.0-beta", + config: {}, + metadata: { environment: "staging" }, + }, + variables: {}, + }, + ]; + + releases = new Releases(sampleReleases); + + // Create a sample context + context = { + desiredReleaseId: null, + deployment: { + id: "deploy-1", + name: "Test Deployment", + }, + environment: { + id: "env-1", + name: "Test Environment", + }, + resource: { + id: "res-1", + name: "Test Resource", + }, + }; + }); + + it("should allow all releases when no version selector is provided", async () => { + // Create a mock getApplicableVersionIds function that returns all versions when no selector + const mockGetApplicableVersionIds = vi + .fn() + .mockImplementation((_, versionIds) => versionIds); + + const rule = new DeploymentVersionSelectorRule(mockGetApplicableVersionIds); + const result = await rule.filter(context, releases); + + // Expect all releases to be allowed + expect(result.allowedReleases.length).toBe(2); + expect(result.rejectionReasons).toBeDefined(); + expect(result.rejectionReasons?.size).toBe(0); + expect(mockGetApplicableVersionIds).toHaveBeenCalledWith(context, [ + "ver-1", + "ver-2", + ]); + }); + + it("should filter releases based on version selector", async () => { + // Mock getApplicableVersionIds to only return the first version ID + const mockGetApplicableVersionIds = vi + .fn() + .mockImplementation((_, versionIds) => [versionIds[0]]); + + const rule = new DeploymentVersionSelectorRule(mockGetApplicableVersionIds); + const result = await rule.filter(context, releases); + + // Expect only the first release to be allowed + expect(result.allowedReleases.length).toBe(1); + expect(result.allowedReleases.at(0)?.id).toBe("rel-1"); + expect(result.rejectionReasons).toBeDefined(); + expect(result.rejectionReasons?.get("rel-2")).toBe( + "Version not in version selector", + ); + }); + + it("should handle async getApplicableVersionIds", async () => { + // Mock getApplicableVersionIds to asynchronously return only the second version ID + const mockGetApplicableVersionIds = vi + .fn() + .mockImplementation(async (_, versionIds) => + Promise.resolve([versionIds[1]]), + ); + + const rule = new DeploymentVersionSelectorRule(mockGetApplicableVersionIds); + const result = await rule.filter(context, releases); + + // Expect only the second release to be allowed + expect(result.allowedReleases.length).toBe(1); + expect(result.allowedReleases.at(0)?.id).toBe("rel-2"); + expect(result.rejectionReasons).toBeDefined(); + expect(result.rejectionReasons?.get("rel-1")).toBe( + "Version not in version selector", + ); + }); + + describe("getApplicableVersionIds function", () => { + it("should handle null selector by returning all version IDs", () => { + const func = getApplicableVersionIds( + null as unknown as Policy["deploymentVersionSelector"], + ); + const result = func(context, ["ver-1", "ver-2"]); + + expect(result).toEqual(["ver-1", "ver-2"]); + }); + }); +}); diff --git a/packages/rule-engine/src/rules/deployment-version-selector-rule.ts b/packages/rule-engine/src/rules/deployment-version-selector-rule.ts new file mode 100644 index 000000000..44653ed0b --- /dev/null +++ b/packages/rule-engine/src/rules/deployment-version-selector-rule.ts @@ -0,0 +1,66 @@ +import { and, inArray } from "@ctrlplane/db"; +import { db } from "@ctrlplane/db/client"; +import * as schema from "@ctrlplane/db/schema"; + +import type { Releases } from "../releases.js"; +import type { + DeploymentResourceContext, + DeploymentResourceRule, + DeploymentResourceRuleResult, + Policy, +} from "../types.js"; + +const REJECTION_REASON = "Version not in version selector"; + +type GetApplicableVersionIdsFunc = ( + context: DeploymentResourceContext, + versionIds: string[], +) => Promise | string[]; + +export class DeploymentVersionSelectorRule implements DeploymentResourceRule { + public readonly name = "DeploymentVersionSelectorRule"; + + constructor(private getApplicableVersionIds: GetApplicableVersionIdsFunc) {} + + async filter( + context: DeploymentResourceContext, + releases: Releases, + ): Promise { + const applicableVersionIds = await this.getApplicableVersionIds( + context, + releases.map((r) => r.version.id), + ); + + const rejectionReasons = new Map(); + return { + allowedReleases: releases.filter((r) => { + const versionId = r.version.id; + if (!applicableVersionIds.includes(versionId)) { + rejectionReasons.set(r.id, REJECTION_REASON); + return false; + } + return true; + }), + rejectionReasons, + }; + } +} + +export const getApplicableVersionIds = + (selector: Policy["deploymentVersionSelector"]) => + (_: DeploymentResourceContext, versionIds: string[]) => { + if (selector == null) return versionIds; + return db + .select({ id: schema.deploymentVersion.id }) + .from(schema.deploymentVersion) + .where( + and( + schema.deploymentVersionMatchesCondition( + db, + selector.deploymentVersionSelector, + ), + inArray(schema.deploymentVersion.id, versionIds), + ), + ) + .then((rows) => rows.map((r) => r.id)); + }; diff --git a/packages/rule-engine/src/types.ts b/packages/rule-engine/src/types.ts index c839054d3..cffe13fde 100644 --- a/packages/rule-engine/src/types.ts +++ b/packages/rule-engine/src/types.ts @@ -65,7 +65,7 @@ export interface DeploymentResourceRule { export type Policy = schema.Policy & { denyWindows: schema.PolicyRuleDenyWindow[]; - deploymentVersionSelector: schema.PolicyDeploymentVersionSelector | null; + deploymentVersionSelector: schema.PolicyRuleDeploymentVersionSelector | null; versionAnyApprovals: schema.PolicyRuleAnyApproval[]; versionUserApprovals: schema.PolicyRuleUserApproval[]; versionRoleApprovals: schema.PolicyRuleRoleApproval[];