diff --git a/packages/api/src/router/deployment-variable.ts b/packages/api/src/router/deployment-variable.ts index 99726356..4a4a1544 100644 --- a/packages/api/src/router/deployment-variable.ts +++ b/packages/api/src/router/deployment-variable.ts @@ -22,21 +22,36 @@ import { variableDeploymentValueTarget, variableDeploymentValueTargetFilter, } from "@ctrlplane/db/schema"; +import { Permission } from "@ctrlplane/validators/auth"; import { createTRPCRouter, protectedProcedure } from "../trpc"; const valueRouter = createTRPCRouter({ - byId: protectedProcedure.query(async () => { - // return ctx.db.value.findMany(); - }), - create: protectedProcedure + .meta({ + authorizationCheck: async ({ canUser, ctx, input }) => { + const variable = await ctx.db + .select() + .from(deploymentVariable) + .where(eq(deploymentVariable.id, input.variableId)) + .then(takeFirst); + return canUser + .perform(Permission.DeploymentUpdate) + .on({ type: "deployment", id: variable.deploymentId }); + }, + }) .input(createDeploymentVariableValue) .mutation(async ({ ctx, input }) => ctx.db.insert(deploymentVariableValue).values(input).returning(), ), setTarget: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.DeploymentUpdate) + .on({ type: "target", id: input.targetId }), + }) .input( z.object({ targetId: z.string().uuid(), @@ -173,6 +188,12 @@ export const deploymentVariableRouter = createTRPCRouter({ value: valueRouter, byTargetId: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.DeploymentGet) + .on({ type: "target", id: input }), + }) .input(z.string().uuid()) .query(({ ctx, input }) => { return ctx.db @@ -208,6 +229,12 @@ export const deploymentVariableRouter = createTRPCRouter({ }), byDeploymentId: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.DeploymentGet) + .on({ type: "deployment", id: input }), + }) .input(z.string().uuid()) .query(async ({ ctx, input }) => ctx.db @@ -243,12 +270,30 @@ export const deploymentVariableRouter = createTRPCRouter({ ), create: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.DeploymentUpdate) + .on({ type: "deployment", id: input.deploymentId }), + }) .input(createDeploymentVariable) .mutation(async ({ ctx, input }) => ctx.db.insert(deploymentVariable).values(input).returning(), ), update: protectedProcedure + .meta({ + authorizationCheck: async ({ canUser, ctx, input }) => { + const variable = await ctx.db + .select() + .from(deploymentVariable) + .where(eq(deploymentVariable.id, input.id)) + .then(takeFirst); + return canUser + .perform(Permission.DeploymentUpdate) + .on({ type: "deployment", id: variable.deploymentId }); + }, + }) .input(z.object({ id: z.string().uuid(), data: updateDeploymentVariable })) .mutation(async ({ ctx, input }) => ctx.db diff --git a/packages/api/src/router/environment.ts b/packages/api/src/router/environment.ts index 3968a202..497f7a39 100644 --- a/packages/api/src/router/environment.ts +++ b/packages/api/src/router/environment.ts @@ -45,6 +45,12 @@ import { createTRPCRouter, protectedProcedure } from "../trpc"; const policyRouter = createTRPCRouter({ deployment: createTRPCRouter({ bySystemId: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemGet) + .on({ type: "system", id: input }), + }) .input(z.string().uuid()) .query(({ ctx, input }) => ctx.db @@ -59,6 +65,12 @@ const policyRouter = createTRPCRouter({ ), create: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemUpdate) + .on({ type: "environment", id: input.environmentId }), + }) .input(createEnvironmentPolicyDeployment) .mutation(({ ctx, input }) => ctx.db @@ -69,6 +81,12 @@ const policyRouter = createTRPCRouter({ ), delete: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemUpdate) + .on({ type: "environment", id: input.environmentId }), + }) .input( z.object({ policyId: z.string().uuid(), @@ -94,6 +112,12 @@ const policyRouter = createTRPCRouter({ approval: createTRPCRouter({ byReleaseId: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.DeploymentGet) + .on({ type: "release", id: input.releaseId }), + }) .input( z.object({ releaseId: z.string(), @@ -123,6 +147,12 @@ const policyRouter = createTRPCRouter({ ), approve: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.DeploymentUpdate) + .on({ type: "release", id: input.releaseId }), + }) .input( z.object({ policyId: z.string().uuid(), releaseId: z.string().uuid() }), ) @@ -166,6 +196,12 @@ const policyRouter = createTRPCRouter({ }), reject: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.DeploymentUpdate) + .on({ type: "release", id: input.releaseId }), + }) .input( z.object({ releaseId: z.string().uuid(), policyId: z.string().uuid() }), ) @@ -184,6 +220,12 @@ const policyRouter = createTRPCRouter({ }), statusByReleasePolicyId: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.DeploymentGet) + .on({ type: "release", id: input.releaseId }), + }) .input( z.object({ releaseId: z.string().uuid(), policyId: z.string().uuid() }), ) @@ -201,36 +243,56 @@ const policyRouter = createTRPCRouter({ ), }), - bySystemId: protectedProcedure.input(z.string()).query(({ ctx, input }) => - ctx.db - .select() - .from(environmentPolicy) - .leftJoin( - environmentPolicyReleaseWindow, - eq(environmentPolicyReleaseWindow.policyId, environmentPolicy.id), - ) - .where(eq(environmentPolicy.systemId, input)) - .then((policies) => - _.chain(policies) - .groupBy("environment_policy.id") - .map((p) => ({ - ...p[0]!.environment_policy, - releaseWindows: p - .map((t) => t.environment_policy_release_window) - .filter(isPresent), - })) - .value(), - ), - ), + bySystemId: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser.perform(Permission.SystemGet).on({ type: "system", id: input }), + }) + .input(z.string().uuid()) + .query(({ ctx, input }) => + ctx.db + .select() + .from(environmentPolicy) + .leftJoin( + environmentPolicyReleaseWindow, + eq(environmentPolicyReleaseWindow.policyId, environmentPolicy.id), + ) + .where(eq(environmentPolicy.systemId, input)) + .then((policies) => + _.chain(policies) + .groupBy("environment_policy.id") + .map((p) => ({ + ...p[0]!.environment_policy, + releaseWindows: p + .map((t) => t.environment_policy_release_window) + .filter(isPresent), + })) + .value(), + ), + ), - byId: protectedProcedure.input(z.string()).query(({ ctx, input }) => - ctx.db.query.environmentPolicy.findMany({ - where: eq(system.id, input), - with: {}, - }), - ), + byId: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemGet) + .on({ type: "environmentPolicy", id: input }), + }) + .input(z.string()) + .query(({ ctx, input }) => + ctx.db.query.environmentPolicy.findMany({ + where: eq(system.id, input), + with: {}, + }), + ), create: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemUpdate) + .on({ type: "system", id: input.systemId }), + }) .input(createEnvironmentPolicy) .mutation(async ({ ctx, input }) => ctx.db.transaction(async (db) => @@ -239,6 +301,12 @@ const policyRouter = createTRPCRouter({ ), update: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemUpdate) + .on({ type: "environmentPolicy", id: input.id }), + }) .input(z.object({ id: z.string().uuid(), data: updateEnvironmentPolicy })) .mutation(({ ctx, input }) => ctx.db @@ -250,6 +318,12 @@ const policyRouter = createTRPCRouter({ ), delete: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemUpdate) + .on({ type: "environmentPolicy", id: input }), + }) .input(z.string().uuid()) .mutation(({ ctx, input }) => ctx.db @@ -260,6 +334,12 @@ const policyRouter = createTRPCRouter({ ), setWindows: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemUpdate) + .on({ type: "environmentPolicy", id: input.policyId }), + }) .input( z.object({ policyId: z.string().uuid(), diff --git a/packages/api/src/router/job.ts b/packages/api/src/router/job.ts index 712ea520..562f881a 100644 --- a/packages/api/src/router/job.ts +++ b/packages/api/src/router/job.ts @@ -1,19 +1,9 @@ import type { Tx } from "@ctrlplane/db"; -import type { JobExecutionStatus } from "@ctrlplane/db/schema"; import _ from "lodash"; import { isPresent } from "ts-is-present"; import { z } from "zod"; -import { - and, - asc, - desc, - eq, - isNull, - notInArray, - or, - takeFirst, -} from "@ctrlplane/db"; +import { and, asc, desc, eq, isNull, or, takeFirst } from "@ctrlplane/db"; import { createJobAgent, deployment, @@ -36,7 +26,7 @@ import { } from "@ctrlplane/job-dispatch"; import { Permission } from "@ctrlplane/validators/auth"; -import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc"; +import { createTRPCRouter, protectedProcedure } from "../trpc"; const jobConfigQuery = (tx: Tx) => tx @@ -90,7 +80,7 @@ const jobConfigRouter = createTRPCRouter({ .meta({ authorizationCheck: ({ canUser, input }) => canUser - .perform(Permission.DeploymentGet) + .perform(Permission.DeploymentGet, Permission.SystemGet) .on( { type: "deployment", id: input.deploymentId }, { type: "environment", id: input.environmentId }, @@ -240,17 +230,25 @@ const rolloutDateFromJobConfig = ( }; const jobAgentRouter = createTRPCRouter({ - byWorkspaceId: publicProcedure + byWorkspaceId: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.JobAgentList) + .on({ type: "workspace", id: input }), + }) .input(z.string().uuid()) .query(({ ctx, input }) => ctx.db.select().from(jobAgent).where(eq(jobAgent.workspaceId, input)), ), - byType: publicProcedure - .input(z.string()) - .query(({ ctx, input }) => - ctx.db.select().from(jobAgent).where(eq(jobAgent.type, input)), - ), + create: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.JobAgentCreate) + .on({ type: "workspace", id: input.workspaceId }), + }) .input(createJobAgent) .mutation(({ ctx, input }) => ctx.db.insert(jobAgent).values(input).returning().then(takeFirst), @@ -258,63 +256,6 @@ const jobAgentRouter = createTRPCRouter({ }); const jobExecutionRouter = createTRPCRouter({ - list: createTRPCRouter({ - byAgentId: publicProcedure - .input(z.string().uuid()) - .query(({ ctx, input }) => - ctx.db - .select() - .from(jobExecution) - .innerJoin(jobConfig, eq(jobConfig.id, jobExecution.jobConfigId)) - .leftJoin(environment, eq(environment.id, jobConfig.environmentId)) - .leftJoin(runbook, eq(runbook.id, jobConfig.runbookId)) - .leftJoin(target, eq(target.id, jobConfig.targetId)) - .leftJoin(release, eq(release.id, jobConfig.releaseId)) - .leftJoin(deployment, eq(deployment.id, release.deploymentId)) - .where( - and( - eq(jobExecution.jobAgentId, input), - notInArray(jobExecution.status, [ - "failure", - "cancelled", - "skipped", - "completed", - ]), - isNull(environment.deletedAt), - ), - ) - .then((r) => - r.map((row) => ({ - ...row.job_execution, - config: row.job_config, - environment: row.environment, - runbook: row.runbook, - target: row.target, - release: { ...row.release, deployment: row.deployment }, - })), - ), - ), - }), - - update: publicProcedure - .input( - z.object({ - id: z.string().uuid(), - data: z.object({ - status: z.string() as z.ZodType, - externalRunId: z.string().optional(), - }), - }), - ) - .mutation(({ ctx, input }) => - ctx.db - .update(jobExecution) - .set(input.data) - .where(eq(jobExecution.id, input.id)) - .returning() - .then(takeFirst), - ), - create: createTRPCRouter({ byEnvId: protectedProcedure .meta({ @@ -344,24 +285,32 @@ const jobExecutionRouter = createTRPCRouter({ }); export const jobRouter = createTRPCRouter({ - byTargetId: protectedProcedure.input(z.string()).query(({ ctx, input }) => - jobConfigQuery(ctx.db) - .where(and(eq(target.id, input), isNull(environment.deletedAt))) - .limit(1_000) - .orderBy(desc(jobExecution.createdAt), desc(jobConfig.createdAt)) - .then((data) => - data.map((t) => ({ - ...t.job_config, - execution: t.job_execution, - agent: t.job_agent, - target: t.target, - deployment: t.deployment, - release: { ...t.release }, - runbook: t.runbook, - environment: t.environment, - })), - ), - ), + byTargetId: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemList) + .on({ type: "target", id: input }), + }) + .input(z.string()) + .query(({ ctx, input }) => + jobConfigQuery(ctx.db) + .where(and(eq(target.id, input), isNull(environment.deletedAt))) + .limit(1_000) + .orderBy(desc(jobExecution.createdAt), desc(jobConfig.createdAt)) + .then((data) => + data.map((t) => ({ + ...t.job_config, + execution: t.job_execution, + agent: t.job_agent, + target: t.target, + deployment: t.deployment, + release: { ...t.release }, + runbook: t.runbook, + environment: t.environment, + })), + ), + ), config: jobConfigRouter, agent: jobAgentRouter, diff --git a/packages/api/src/router/release.ts b/packages/api/src/router/release.ts index 483843ae..19b7c0e2 100644 --- a/packages/api/src/router/release.ts +++ b/packages/api/src/router/release.ts @@ -31,7 +31,7 @@ export const releaseRouter = createTRPCRouter({ .meta({ authorizationCheck: ({ canUser, input }) => canUser - .perform(Permission.DeploymentGet) + .perform(Permission.ReleaseList) .on({ type: "deployment", id: input.deploymentId }), }) .input( @@ -70,7 +70,7 @@ export const releaseRouter = createTRPCRouter({ .meta({ authorizationCheck: ({ canUser, input }) => canUser - .perform(Permission.DeploymentGet) + .perform(Permission.ReleaseGet) .on({ type: "release", id: input }), }) .input(z.string().uuid()) @@ -103,7 +103,7 @@ export const releaseRouter = createTRPCRouter({ .meta({ authorizationCheck: ({ canUser, input }) => canUser - .perform(Permission.DeploymentGet) + .perform(Permission.DeploymentGet, Permission.ReleaseGet) .on( { type: "release", id: input.releaseId }, { type: "environment", id: input.environmentId }, @@ -132,7 +132,7 @@ export const releaseRouter = createTRPCRouter({ .meta({ authorizationCheck: ({ canUser, input }) => canUser - .perform(Permission.DeploymentUpdate) + .perform(Permission.ReleaseCreate) .on({ type: "deployment", id: input.deploymentId }), }) .input(createRelease) @@ -171,6 +171,13 @@ export const releaseRouter = createTRPCRouter({ ), blockedEnvironments: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser.perform(Permission.ReleaseGet).on( + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + input.map((releaseId: any) => ({ type: "release", id: releaseId })), + ), + }) .input(z.array(z.string().uuid())) .query(async ({ input }) => { const policies = await db diff --git a/packages/api/src/router/target.ts b/packages/api/src/router/target.ts index 131de4d0..74c89717 100644 --- a/packages/api/src/router/target.ts +++ b/packages/api/src/router/target.ts @@ -213,6 +213,12 @@ const targetProviderRouter = createTRPCRouter({ managed: createTRPCRouter({ google: createTRPCRouter({ create: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.TargetUpdate) + .on({ type: "workspace", id: input.workspaceId }), + }) .input( createTargetProvider.and( z.object({ diff --git a/packages/api/src/router/user.ts b/packages/api/src/router/user.ts index 224ae69e..db8c2f70 100644 --- a/packages/api/src/router/user.ts +++ b/packages/api/src/router/user.ts @@ -3,8 +3,9 @@ import { omit } from "lodash"; import { v4 } from "uuid"; import { z } from "zod"; +import { can } from "@ctrlplane/auth/utils"; import { and, eq, takeFirst } from "@ctrlplane/db"; -import { user, userApiKey } from "@ctrlplane/db/schema"; +import { scopeType, user, userApiKey } from "@ctrlplane/db/schema"; import { createTRPCRouter, protectedProcedure } from "../trpc"; @@ -24,6 +25,21 @@ export const profileRouter = createTRPCRouter({ }); export const userRouter = createTRPCRouter({ + can: protectedProcedure + .input( + z.object({ + action: z.string(), + resource: z.object({ + type: z.enum(scopeType.enumValues), + id: z.string().uuid(), + }), + }), + ) + .query(async ({ ctx, input }) => { + const { action, resource } = input; + return can().user(ctx.session.user.id).perform(action).on(resource); + }), + viewer: protectedProcedure.query(({ ctx }) => ctx.db .select() diff --git a/packages/api/src/router/value-set.ts b/packages/api/src/router/value-set.ts index abb3d19b..1ee9a830 100644 --- a/packages/api/src/router/value-set.ts +++ b/packages/api/src/router/value-set.ts @@ -9,11 +9,16 @@ import { value, valueSet, } from "@ctrlplane/db/schema"; +import { Permission } from "@ctrlplane/validators/auth"; import { createTRPCRouter, protectedProcedure } from "../trpc"; export const valueSetRouter = createTRPCRouter({ bySystemId: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser.perform(Permission.SystemGet).on({ type: "system", id: input }), + }) .input(z.string().uuid()) .query(async ({ ctx, input }) => ctx.db @@ -33,22 +38,48 @@ export const valueSetRouter = createTRPCRouter({ ), ), - create: protectedProcedure.input(createValueSet).mutation(({ ctx, input }) => - ctx.db.transaction(async (db) => { - const vs = await db - .insert(valueSet) - .values(input) - .returning() - .then(takeFirst); - const values = await db - .insert(value) - .values(input.values.map((value) => ({ ...value, valueSetId: vs.id }))) - .returning(); - return { ...vs, values }; - }), - ), - delete: protectedProcedure.input(z.string().uuid()).mutation(() => {}), + create: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemUpdate) + .on({ type: "system", id: input.systemId }), + }) + .input(createValueSet) + .mutation(({ ctx, input }) => + ctx.db.transaction(async (db) => { + const vs = await db + .insert(valueSet) + .values(input) + .returning() + .then(takeFirst); + const values = await db + .insert(value) + .values( + input.values.map((value) => ({ ...value, valueSetId: vs.id })), + ) + .returning(); + return { ...vs, values }; + }), + ), + + delete: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemUpdate) + .on({ type: "valueSet", id: input }), + }) + .input(z.string().uuid()) + .mutation(() => {}), + set: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.SystemUpdate) + .on({ type: "valueSet", id: input.id }), + }) .input( z.object({ id: z.string().uuid(), diff --git a/packages/api/src/router/workspace.ts b/packages/api/src/router/workspace.ts index 6f516dd0..19b8d944 100644 --- a/packages/api/src/router/workspace.ts +++ b/packages/api/src/router/workspace.ts @@ -14,12 +14,18 @@ import { workspace, workspaceInviteToken, } from "@ctrlplane/db/schema"; -import { predefinedRoles } from "@ctrlplane/validators/auth"; +import { Permission, predefinedRoles } from "@ctrlplane/validators/auth"; import { createTRPCRouter, protectedProcedure } from "../trpc"; const membersRouter = createTRPCRouter({ list: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.WorkspaceListMembers) + .on({ type: "workspace", id: input }), + }) .input(z.string().uuid()) .query(async ({ ctx, input }) => ctx.db @@ -122,6 +128,12 @@ const inviteRouter = createTRPCRouter({ ), create: protectedProcedure + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.WorkspaceInvite) + .on({ type: "workspace", id: input.workspaceId }), + }) .input( z.object({ roleId: z.string().uuid(), @@ -158,7 +170,7 @@ export const workspaceRouter = createTRPCRouter({ ), update: protectedProcedure - .input(z.object({ id: z.string(), data: updateWorkspace })) + .input(z.object({ id: z.string().uuid(), data: updateWorkspace })) .mutation(async ({ ctx, input }) => ctx.db .update(workspace) @@ -202,22 +214,36 @@ export const workspaceRouter = createTRPCRouter({ ), bySlug: protectedProcedure - .input(z.string()) + .input(z.string().uuid()) .query(async ({ ctx, input }) => ctx.db .select() .from(workspace) - .where(eq(workspace.slug, input)) - .then(takeFirstOrNull), + .innerJoin(entityRole, eq(workspace.id, entityRole.scopeId)) + .where( + and( + eq(workspace.slug, input), + eq(entityRole.entityId, ctx.session.user.id), + ), + ) + .then(takeFirstOrNull) + .then((workspace) => workspace?.workspace ?? null), ), byId: protectedProcedure - .input(z.string()) + .input(z.string().uuid()) .query(async ({ ctx, input }) => ctx.db .select() .from(workspace) - .where(eq(workspace.id, input)) - .then(takeFirstOrNull), + .innerJoin(entityRole, eq(workspace.id, entityRole.scopeId)) + .where( + and( + eq(workspace.id, input), + eq(entityRole.entityId, ctx.session.user.id), + ), + ) + .then(takeFirstOrNull) + .then((w) => w?.workspace ?? null), ), }); diff --git a/packages/auth/src/utils/rbac.ts b/packages/auth/src/utils/rbac.ts index 7fce771a..793a309b 100644 --- a/packages/auth/src/utils/rbac.ts +++ b/packages/auth/src/utils/rbac.ts @@ -6,6 +6,8 @@ import { deployment, entityRole, environment, + environmentPolicy, + jobAgent, release, role, rolePermission, @@ -13,6 +15,7 @@ import { target, targetLabelGroup, targetProvider, + valueSet, workspace, } from "@ctrlplane/db/schema"; @@ -86,8 +89,11 @@ const fetchScopeHierarchyForResource = async (resource: { system: getSystemScopes, workspace: getWorkspaceScopes, environment: getEnvironmentScopes, + environmentPolicy: getEnvironmentPolicyScopes, release: getReleaseScopes, targetLabelGroup: getTargetLabelGroupScopes, + valueSet: getValueSetScopes, + jobAgent: getJobAgentScopes, }; const handler = scopeHandlers[resource.type]; @@ -101,7 +107,7 @@ const getReleaseScopes = async (id: string) => { .innerJoin(system, eq(system.workspaceId, workspace.id)) .innerJoin(deployment, eq(deployment.systemId, system.id)) .innerJoin(release, eq(release.deploymentId, deployment.id)) - .where(eq(deployment.id, id)) + .where(eq(release.id, id)) .then(takeFirst); return [ @@ -118,7 +124,7 @@ const getEnvironmentScopes = async (id: string) => { .from(workspace) .innerJoin(system, eq(system.workspaceId, workspace.id)) .innerJoin(environment, eq(environment.systemId, system.id)) - .where(eq(target.id, id)) + .where(eq(environment.id, id)) .then(takeFirst); return [ @@ -128,12 +134,44 @@ const getEnvironmentScopes = async (id: string) => { ]; }; +const getEnvironmentPolicyScopes = async (id: string) => { + const result = await db + .select() + .from(workspace) + .innerJoin(system, eq(system.workspaceId, workspace.id)) + .innerJoin(environmentPolicy, eq(environmentPolicy.systemId, system.id)) + .where(eq(environmentPolicy.id, id)) + .then(takeFirst); + + return [ + { type: "environmentPolicy" as const, id: result.environment_policy.id }, + { type: "system" as const, id: result.system.id }, + { type: "workspace" as const, id: result.workspace.id }, + ]; +}; + +const getValueSetScopes = async (id: string) => { + const result = await db + .select() + .from(workspace) + .innerJoin(system, eq(system.workspaceId, workspace.id)) + .innerJoin(valueSet, eq(valueSet.systemId, system.id)) + .where(eq(valueSet.id, id)) + .then(takeFirst); + + return [ + { type: "valueSet" as const, id: result.value_set.id }, + { type: "system" as const, id: result.system.id }, + { type: "workspace" as const, id: result.workspace.id }, + ]; +}; + const getTargetLabelGroupScopes = async (id: string) => { const result = await db .select() .from(workspace) .innerJoin(targetLabelGroup, eq(targetLabelGroup.workspaceId, workspace.id)) - .where(eq(target.id, id)) + .where(eq(targetLabelGroup.id, id)) .then(takeFirst); return [ @@ -209,3 +247,17 @@ const getWorkspaceScopes = async (id: string) => { return [{ type: "workspace" as const, id: result.id }]; }; + +const getJobAgentScopes = async (id: string) => { + const result = await db + .select() + .from(workspace) + .innerJoin(jobAgent, eq(jobAgent.workspaceId, workspace.id)) + .where(eq(jobAgent.id, id)) + .then(takeFirst); + + return [ + { type: "jobAgent" as const, id: result.job_agent.id }, + { type: "workspace" as const, id: result.workspace.id }, + ]; +}; diff --git a/packages/db/drizzle/0010_fearless_blink.sql b/packages/db/drizzle/0010_fearless_blink.sql new file mode 100644 index 00000000..27bf8ac7 --- /dev/null +++ b/packages/db/drizzle/0010_fearless_blink.sql @@ -0,0 +1,3 @@ +ALTER TYPE "scope_type" ADD VALUE 'environmentPolicy';--> statement-breakpoint +ALTER TYPE "scope_type" ADD VALUE 'valueSet';--> statement-breakpoint +ALTER TYPE "scope_type" ADD VALUE 'jobAgent'; \ No newline at end of file diff --git a/packages/db/drizzle/meta/0010_snapshot.json b/packages/db/drizzle/meta/0010_snapshot.json new file mode 100644 index 00000000..aa38c806 --- /dev/null +++ b/packages/db/drizzle/meta/0010_snapshot.json @@ -0,0 +1,2749 @@ +{ + "id": "4c8c1c22-29f2-4038-8cb7-6d8f939f9087", + "prevId": "cb4637b7-56d5-4a57-9c54-4189012c33ef", + "version": "6", + "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": "varchar(255)", + "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": "varchar(255)", + "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": "varchar(255)", + "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" + } + }, + "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 + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "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 + }, + "schema": { + "name": "schema", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "deployment_variable_deployment_id_key_index": { + "name": "deployment_variable_deployment_id_key_index", + "columns": ["deployment_id", "key"], + "isUnique": true + } + }, + "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": "no action", + "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 + } + }, + "indexes": { + "deployment_variable_value_variable_id_value_index": { + "name": "deployment_variable_value_variable_id_value_index", + "columns": ["variable_id", "value"], + "isUnique": true + } + }, + "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": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_variable_value_target": { + "name": "deployment_variable_value_target", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "variable_value_id": { + "name": "variable_value_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "target_id": { + "name": "target_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "deployment_variable_value_target_variable_value_id_target_id_index": { + "name": "deployment_variable_value_target_variable_value_id_target_id_index", + "columns": ["variable_value_id", "target_id"], + "isUnique": true + } + }, + "foreignKeys": { + "deployment_variable_value_target_variable_value_id_deployment_variable_value_id_fk": { + "name": "deployment_variable_value_target_variable_value_id_deployment_variable_value_id_fk", + "tableFrom": "deployment_variable_value_target", + "tableTo": "deployment_variable_value", + "columnsFrom": ["variable_value_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_variable_value_target_target_id_target_id_fk": { + "name": "deployment_variable_value_target_target_id_target_id_fk", + "tableFrom": "deployment_variable_value_target", + "tableTo": "target", + "columnsFrom": ["target_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_variable_value_target_filter": { + "name": "deployment_variable_value_target_filter", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "variable_value_id": { + "name": "variable_value_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "labels": { + "name": "labels", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_variable_value_target_filter_variable_value_id_deployment_variable_value_id_fk": { + "name": "deployment_variable_value_target_filter_variable_value_id_deployment_variable_value_id_fk", + "tableFrom": "deployment_variable_value_target_filter", + "tableTo": "deployment_variable_value", + "columnsFrom": ["variable_value_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": "'{}'" + }, + "github_config_file_id": { + "name": "github_config_file_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "deployment_system_id_slug_index": { + "name": "deployment_system_id_slug_index", + "columns": ["system_id", "slug"], + "isUnique": true + } + }, + "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": "no action", + "onUpdate": "no action" + }, + "deployment_github_config_file_id_github_config_file_id_fk": { + "name": "deployment_github_config_file_id_github_config_file_id_fk", + "tableFrom": "deployment", + "tableTo": "github_config_file", + "columnsFrom": ["github_config_file_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_meta_dependency": { + "name": "deployment_meta_dependency", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "depends_on_id": { + "name": "depends_on_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "deployment_meta_dependency_depends_on_id_deployment_id_index": { + "name": "deployment_meta_dependency_depends_on_id_deployment_id_index", + "columns": ["depends_on_id", "deployment_id"], + "isUnique": true + } + }, + "foreignKeys": { + "deployment_meta_dependency_deployment_id_deployment_id_fk": { + "name": "deployment_meta_dependency_deployment_id_deployment_id_fk", + "tableFrom": "deployment_meta_dependency", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployment_meta_dependency_depends_on_id_deployment_id_fk": { + "name": "deployment_meta_dependency_depends_on_id_deployment_id_fk", + "tableFrom": "deployment_meta_dependency", + "tableTo": "deployment", + "columnsFrom": ["depends_on_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "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 + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "target_filter": { + "name": "target_filter", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "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_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 + }, + "approval_required": { + "name": "approval_required", + "type": "environment_policy_approval_requirement", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'manual'" + }, + "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_type": { + "name": "concurrency_type", + "type": "concurrency_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'all'" + }, + "concurrency_limit": { + "name": "concurrency_limit", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "duration": { + "name": "duration", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "evaluate_with": { + "name": "evaluate_with", + "type": "evaluation_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + }, + "evaluate": { + "name": "evaluate", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "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": "no action", + "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'" + } + }, + "indexes": { + "environment_policy_approval_policy_id_release_id_index": { + "name": "environment_policy_approval_policy_id_release_id_index", + "columns": ["policy_id", "release_id"], + "isUnique": true + } + }, + "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_release_id_fk": { + "name": "environment_policy_approval_release_id_release_id_fk", + "tableFrom": "environment_policy_approval", + "tableTo": "release", + "columnsFrom": ["release_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "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": ["policy_id", "environment_id"], + "isUnique": true + } + }, + "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_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.github_config_file": { + "name": "github_config_file", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "repository_name": { + "name": "repository_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "unique_organization_repository_path": { + "name": "unique_organization_repository_path", + "columns": ["organization_id", "repository_name", "path"], + "isUnique": true + } + }, + "foreignKeys": { + "github_config_file_organization_id_github_organization_id_fk": { + "name": "github_config_file_organization_id_github_organization_id_fk", + "tableFrom": "github_config_file", + "tableTo": "github_organization", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "github_config_file_workspace_id_workspace_id_fk": { + "name": "github_config_file_workspace_id_workspace_id_fk", + "tableFrom": "github_config_file", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.github_organization": { + "name": "github_organization", + "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 + }, + "organization_name": { + "name": "organization_name", + "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()" + }, + "connected": { + "name": "connected", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'main'" + } + }, + "indexes": {}, + "foreignKeys": { + "github_organization_added_by_user_id_user_id_fk": { + "name": "github_organization_added_by_user_id_user_id_fk", + "tableFrom": "github_organization", + "tableTo": "user", + "columnsFrom": ["added_by_user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "github_organization_workspace_id_workspace_id_fk": { + "name": "github_organization_workspace_id_workspace_id_fk", + "tableFrom": "github_organization", + "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.target": { + "name": "target", + "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": "'{}'" + }, + "labels": { + "name": "labels", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "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 + } + }, + "indexes": { + "target_identifier_workspace_id_index": { + "name": "target_identifier_workspace_id_index", + "columns": ["identifier", "workspace_id"], + "isUnique": true + } + }, + "foreignKeys": { + "target_provider_id_target_provider_id_fk": { + "name": "target_provider_id_target_provider_id_fk", + "tableFrom": "target", + "tableTo": "target_provider", + "columnsFrom": ["provider_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "target_workspace_id_workspace_id_fk": { + "name": "target_workspace_id_workspace_id_fk", + "tableFrom": "target", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "target_name_unique": { + "name": "target_name_unique", + "nullsNotDistinct": false, + "columns": ["name"] + } + } + }, + "public.target_schema": { + "name": "target_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": { + "target_schema_version_kind_workspace_id_index": { + "name": "target_schema_version_kind_workspace_id_index", + "columns": ["version", "kind", "workspace_id"], + "isUnique": true + } + }, + "foreignKeys": { + "target_schema_workspace_id_workspace_id_fk": { + "name": "target_schema_workspace_id_workspace_id_fk", + "tableFrom": "target_schema", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.target_provider": { + "name": "target_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": { + "target_provider_workspace_id_name_index": { + "name": "target_provider_workspace_id_name_index", + "columns": ["workspace_id", "name"], + "isUnique": true + } + }, + "foreignKeys": { + "target_provider_workspace_id_workspace_id_fk": { + "name": "target_provider_workspace_id_workspace_id_fk", + "tableFrom": "target_provider", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.target_provider_google": { + "name": "target_provider_google", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "target_provider_id": { + "name": "target_provider_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_ids": { + "name": "project_ids", + "type": "text[]", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "target_provider_google_target_provider_id_target_provider_id_fk": { + "name": "target_provider_google_target_provider_id_target_provider_id_fk", + "tableFrom": "target_provider_google", + "tableTo": "target_provider", + "columnsFrom": ["target_provider_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()" + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "release_deployment_id_version_index": { + "name": "release_deployment_id_version_index", + "columns": ["deployment_id", "version"], + "isUnique": true + } + }, + "foreignKeys": { + "release_deployment_id_deployment_id_fk": { + "name": "release_deployment_id_deployment_id_fk", + "tableFrom": "release", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.release_dependency": { + "name": "release_dependency", + "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 + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "target_label_group_id": { + "name": "target_label_group_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "rule_type": { + "name": "rule_type", + "type": "release_dependency_rule_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "rule": { + "name": "rule", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "release_dependency_release_id_deployment_id_target_label_group_id_index": { + "name": "release_dependency_release_id_deployment_id_target_label_group_id_index", + "columns": ["release_id", "deployment_id", "target_label_group_id"], + "isUnique": true + } + }, + "foreignKeys": { + "release_dependency_release_id_release_id_fk": { + "name": "release_dependency_release_id_release_id_fk", + "tableFrom": "release_dependency", + "tableTo": "release", + "columnsFrom": ["release_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_dependency_deployment_id_deployment_id_fk": { + "name": "release_dependency_deployment_id_deployment_id_fk", + "tableFrom": "release_dependency", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_dependency_target_label_group_id_target_label_group_id_fk": { + "name": "release_dependency_target_label_group_id_target_label_group_id_fk", + "tableFrom": "release_dependency", + "tableTo": "target_label_group", + "columnsFrom": ["target_label_group_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": ["workspace_id", "slug"], + "isUnique": true + } + }, + "foreignKeys": { + "system_workspace_id_workspace_id_fk": { + "name": "system_workspace_id_workspace_id_fk", + "tableFrom": "system", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "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": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "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": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "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": ["team_id", "user_id"], + "isUnique": true + } + }, + "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_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": ["workspace_id", "name"], + "isUnique": true + } + }, + "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.job_config": { + "name": "job_config", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "type": { + "name": "type", + "type": "job_config_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "caused_by_id": { + "name": "caused_by_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "target_id": { + "name": "target_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "runbook_id": { + "name": "runbook_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "job_config_caused_by_id_user_id_fk": { + "name": "job_config_caused_by_id_user_id_fk", + "tableFrom": "job_config", + "tableTo": "user", + "columnsFrom": ["caused_by_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "job_config_release_id_release_id_fk": { + "name": "job_config_release_id_release_id_fk", + "tableFrom": "job_config", + "tableTo": "release", + "columnsFrom": ["release_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "job_config_target_id_target_id_fk": { + "name": "job_config_target_id_target_id_fk", + "tableFrom": "job_config", + "tableTo": "target", + "columnsFrom": ["target_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "job_config_environment_id_environment_id_fk": { + "name": "job_config_environment_id_environment_id_fk", + "tableFrom": "job_config", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "job_config_runbook_id_runbook_id_fk": { + "name": "job_config_runbook_id_runbook_id_fk", + "tableFrom": "job_config", + "tableTo": "runbook", + "columnsFrom": ["runbook_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job_execution": { + "name": "job_execution", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_config_id": { + "name": "job_config_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "external_run_id": { + "name": "external_run_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "job_execution_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "job_execution_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'policy_passing'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "job_execution_job_config_id_job_config_id_fk": { + "name": "job_execution_job_config_id_job_config_id_fk", + "tableFrom": "job_execution", + "tableTo": "job_config", + "columnsFrom": ["job_config_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "job_execution_job_agent_id_job_agent_id_fk": { + "name": "job_execution_job_agent_id_job_agent_id_fk", + "tableFrom": "job_execution", + "tableTo": "job_agent", + "columnsFrom": ["job_agent_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 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_slug_unique": { + "name": "workspace_slug_unique", + "nullsNotDistinct": false, + "columns": ["slug"] + } + } + }, + "public.value": { + "name": "value", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "value_set_id": { + "name": "value_set_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "value_value_set_id_key_value_index": { + "name": "value_value_set_id_key_value_index", + "columns": ["value_set_id", "key", "value"], + "isUnique": true + } + }, + "foreignKeys": { + "value_value_set_id_value_set_id_fk": { + "name": "value_value_set_id_value_set_id_fk", + "tableFrom": "value", + "tableTo": "value_set", + "columnsFrom": ["value_set_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.value_set": { + "name": "value_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": { + "value_set_system_id_system_id_fk": { + "name": "value_set_system_id_system_id_fk", + "tableFrom": "value_set", + "tableTo": "system", + "columnsFrom": ["system_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "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.target_label_group": { + "name": "target_label_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 + } + }, + "indexes": {}, + "foreignKeys": { + "target_label_group_workspace_id_workspace_id_fk": { + "name": "target_label_group_workspace_id_workspace_id_fk", + "tableFrom": "target_label_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 + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "runbook_id": { + "name": "runbook_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "default_value": { + "name": "default_value", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "schema": { + "name": "schema", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "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": "no action", + "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": [ + "role_id", + "entity_type", + "entity_id", + "scope_id", + "scope_type" + ], + "isUnique": true + } + }, + "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": false + } + }, + "indexes": { + "role_permission_role_id_permission_index": { + "name": "role_permission_role_id_permission_index", + "columns": ["role_id", "permission"], + "isUnique": true + } + }, + "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": {} + } + }, + "enums": { + "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.concurrency_type": { + "name": "concurrency_type", + "schema": "public", + "values": ["all", "some"] + }, + "public.environment_policy_deployment_success_type": { + "name": "environment_policy_deployment_success_type", + "schema": "public", + "values": ["all", "some", "optional"] + }, + "public.evaluation_type": { + "name": "evaluation_type", + "schema": "public", + "values": ["semver", "regex", "none"] + }, + "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.release_dependency_rule_type": { + "name": "release_dependency_rule_type", + "schema": "public", + "values": ["regex", "semver"] + }, + "public.job_config_type": { + "name": "job_config_type", + "schema": "public", + "values": [ + "new_release", + "new_target", + "target_changed", + "api", + "redeploy", + "runbook" + ] + }, + "public.job_execution_reason": { + "name": "job_execution_reason", + "schema": "public", + "values": [ + "policy_passing", + "policy_override", + "env_policy_override", + "config_policy_override" + ] + }, + "public.job_execution_status": { + "name": "job_execution_status", + "schema": "public", + "values": [ + "completed", + "cancelled", + "skipped", + "in_progress", + "action_required", + "pending", + "failure", + "invalid_job_agent", + "invalid_integration", + "external_run_not_found" + ] + }, + "public.entity_type": { + "name": "entity_type", + "schema": "public", + "values": ["user", "team"] + }, + "public.scope_type": { + "name": "scope_type", + "schema": "public", + "values": [ + "release", + "target", + "targetProvider", + "targetLabelGroup", + "workspace", + "environment", + "environmentPolicy", + "valueSet", + "system", + "deployment", + "jobAgent" + ] + } + }, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index d3151e59..b88cf530 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -71,6 +71,13 @@ "when": 1725655538592, "tag": "0009_flashy_pyro", "breakpoints": true + }, + { + "idx": 10, + "version": "6", + "when": 1725682116384, + "tag": "0010_fearless_blink", + "breakpoints": true } ] } diff --git a/packages/db/src/schema/rbac.ts b/packages/db/src/schema/rbac.ts index 6572f6e1..7715b101 100644 --- a/packages/db/src/schema/rbac.ts +++ b/packages/db/src/schema/rbac.ts @@ -38,8 +38,11 @@ export const scopeType = pgEnum("scope_type", [ "targetLabelGroup", "workspace", "environment", + "environmentPolicy", + "valueSet", "system", "deployment", + "jobAgent", ]); export const scopeTypeSchema = z.enum(scopeType.enumValues); export type ScopeType = z.infer; diff --git a/packages/validators/src/auth/index.ts b/packages/validators/src/auth/index.ts index 4762fb3a..bf52a4ab 100644 --- a/packages/validators/src/auth/index.ts +++ b/packages/validators/src/auth/index.ts @@ -4,6 +4,9 @@ export enum Permission { WorkspaceInvite = "workspace.invite", WorkspaceListMembers = "workspace.listMembers", + JobAgentList = "jobAgent.list", + JobAgentCreate = "jobAgent.create", + RoleCreate = "role.create", RoleDelete = "role.delete", RoleGet = "role.get",