Skip to content

feat: migrate all resolvers into new organization#6539

Draft
Jabolol wants to merge 9 commits intomainfrom
jabolol/graphql-reorg-resolvrs
Draft

feat: migrate all resolvers into new organization#6539
Jabolol wants to merge 9 commits intomainfrom
jabolol/graphql-reorg-resolvrs

Conversation

@Jabolol
Copy link
Contributor

@Jabolol Jabolol commented Feb 5, 2026

This PR closes #6532, closes #6538, closes #6382.

Warning

This PR does NOT delete old resolver files for comparison reasons yet. Once everything is ready to migrate, they'll be removed.

  • feat: migrate all resolvers into new organization
  • add: no-inline-resolver-types eslint rule
  • add: orgId param to invitation resolver
  • chore: use new resolvers
  • add: new resource permissions columns
  • add: jsdoc deprecated comments
  • chore: run codegen scripts
  • fix: expose missing resolvers

Resolver Migration Summary

Generated: 2026-02-05T02:05:08.314Z

Migration Coverage

  • Total functions in OLD structure: 204
  • Successfully migrated: 204
    • With changes: 147
    • Unchanged (same LOC): 57
  • Missing migrations: 0
  • Migration progress: 100.0%

Migrated Functions (With Changes)

organization/ (34 functions)
data-connection/ (1 functions)

createDataConnection (+6/-11)

Location: data-connection.ts:104organization/data-connection/mutations.ts:79

View Diff
===================================================================
--- data-connection.ts	OLD
+++ organization/data-connection/mutations.ts	NEW
@@ -1,10 +1,6 @@
 createDataConnection: async (
   _: unknown,
-  {
-    input,
-  }: {
-    input: z.infer<typeof CreateDataConnectionSchema>;
-  },
+  { input }: MutationCreateDataConnectionArgs,
   context: GraphQLContext,
 ) => {
   const authenticatedUser = requireAuthentication(context.user);
@@ -13,10 +9,9 @@
     input,
   );
 
-  await requireOrgMembership(authenticatedUser.userId, orgId);
+  const { client } = await getOrgScopedClient(context, orgId);
 
-  const supabase = createAdminClient();
-  const { data: org, error: orgError } = await supabase
+  const { data: org, error: orgError } = await client
     .from("organizations")
     .select()
     .eq("id", orgId)
@@ -26,7 +21,7 @@
   }
   validateDynamicConnector(name, type, org.org_name);
 
-  const { data, error } = await supabase
+  const { data, error } = await client
     .from("dynamic_connectors")
     .insert({
       org_id: orgId,
@@ -51,11 +46,11 @@
   );
   if (trinoError) {
     // Best effort try to cleanup the connector from supabase
-    await supabase.from("dynamic_connectors").delete().eq("id", data.id);
+    await client.from("dynamic_connectors").delete().eq("id", data.id);
     throw ServerErrors.externalService(`Error creating catalog: ${trinoError}`);
   }
 
-  await syncDataConnection(supabase, authenticatedUser.userId, data);
+  await syncDataConnection(client, authenticatedUser.userId, data);
 
   return {
     success: true,
data-ingestion/ (1 functions)

createDataIngestionConfig (+12/-12)

Location: data-ingestion.ts:26organization/data-ingestion/mutations.ts:22

View Diff
===================================================================
--- data-ingestion.ts	OLD
+++ organization/data-ingestion/mutations.ts	NEW
@@ -1,13 +1,14 @@
 createDataIngestionConfig: async (
   _: unknown,
-  args: { input: z.infer<typeof CreateDataIngestionSchema> },
+  args: MutationCreateDataIngestionConfigArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const input = validateInput(CreateDataIngestionSchema, args.input);
-  const supabase = createAdminClient();
 
-  const { data: dataset, error: datasetError } = await supabase
+  // TODO(jabolo): This is incorrect, dataset id is not an org id
+  const { client } = await getOrgScopedClient(context, input.datasetId);
+
+  const { data: dataset, error: datasetError } = await client
     .from("datasets")
     .select("*")
     .eq("id", input.datasetId)
@@ -20,13 +21,12 @@
     throw ResourceErrors.notFound("Dataset not found");
   }
 
-  if (
-    !(await checkMembershipExists(authenticatedUser.userId, dataset.org_id))
-  ) {
-    throw AuthenticationErrors.notAuthorized();
-  }
+  const { client: orgClient } = await getOrgScopedClient(
+    context,
+    dataset.org_id,
+  );
 
-  const { data: existingConfig } = await supabase
+  const { data: existingConfig } = await orgClient
     .from("data_ingestions")
     .select("id")
     .eq("dataset_id", input.datasetId)
@@ -34,7 +34,7 @@
     .maybeSingle();
 
   const { data: config, error: configError } = existingConfig
-    ? await supabase
+    ? await orgClient
         .from("data_ingestions")
         .update({
           factory_type: input.factoryType,
@@ -43,7 +43,7 @@
         .eq("id", existingConfig.id)
         .select()
         .single()
-    : await supabase
+    : await orgClient
         .from("data_ingestions")
         .insert({
           dataset_id: input.datasetId,
data-model/ (1 functions)

createDataModel (+4/-9)

Location: data-model.ts:58organization/data-model/mutations.ts:18

View Diff
===================================================================
--- data-model.ts	OLD
+++ organization/data-model/mutations.ts	NEW
@@ -1,18 +1,13 @@
 createDataModel: async (
   _: unknown,
-  {
-    input,
-  }: {
-    input: z.infer<typeof CreateDataModelSchema>;
-  },
+  { input }: MutationCreateDataModelArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const validatedInput = validateInput(CreateDataModelSchema, input);
-  await requireOrgMembership(authenticatedUser.userId, validatedInput.orgId);
 
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+  const { client } = await getOrgScopedClient(context, validatedInput.orgId);
+
+  const { data, error } = await client
     .from("model")
     .insert({
       org_id: validatedInput.orgId,
dataset/ (1 functions)

createDataset (+6/-8)

Location: dataset.ts:61organization/dataset/mutations.ts:19

View Diff
===================================================================
--- dataset.ts	OLD
+++ organization/dataset/mutations.ts	NEW
@@ -1,25 +1,23 @@
 createDataset: async (
   _: unknown,
-  { input }: { input: z.infer<typeof CreateDatasetSchema> },
+  { input }: MutationCreateDatasetArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const validated = validateInput(CreateDatasetSchema, input);
-  const organization = await getOrganization(validated.orgId);
-  await requireOrgMembership(authenticatedUser.userId, organization.id);
 
-  const supabase = createAdminClient();
+  const { client, userId } = await getOrgScopedClient(context, validated.orgId);
+
   const datasetId = uuidv4();
 
-  const { data: dataset, error } = await supabase
+  const { data: dataset, error } = await client
     .from("datasets")
     .insert({
       id: datasetId,
-      org_id: organization.id,
+      org_id: validated.orgId,
       name: validated.name,
       display_name: validated.displayName,
       description: validated.description,
-      created_by: authenticatedUser.userId,
+      created_by: userId,
       is_public: validated.isPublic ?? false,
       dataset_type: validated.type,
     })
invitation/ (12 functions)

createInvitation (+13/-13)

Location: invitation.ts:48organization/invitation/mutations.ts:28

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/mutations.ts	NEW
@@ -1,25 +1,24 @@
 createInvitation: async (
   _: unknown,
-  args: { input: { orgId: string; email: string; role: string } },
+  args: MutationCreateInvitationArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const input = validateInput(CreateInvitationSchema, args.input);
 
-  const supabase = createAdminClient();
-  const org = await requireOrganizationAccess(
-    authenticatedUser.userId,
-    input.orgId,
-  );
-  const userProfile = await getUserProfile(authenticatedUser.userId);
+  const { client, userId } = await getOrgScopedClient(context, input.orgId);
+  const userProfile = await getUserProfile(userId, client);
+  const org = await getOrganization(input.orgId, client);
 
   const normalizedEmail = input.email.toLowerCase().trim();
 
-  if (authenticatedUser.email?.toLowerCase() === normalizedEmail) {
-    throw InvitationErrors.cannotInviteSelf();
+  if (context.user.role === "user" && context.user.email) {
+    const authenticatedEmail = context.user.email.toLowerCase();
+    if (authenticatedEmail === normalizedEmail) {
+      throw InvitationErrors.cannotInviteSelf();
+    }
   }
 
-  const { data: existingUser } = await supabase
+  const { data: existingUser } = await client
     .from("user_profiles")
     .select("id")
     .ilike("email", normalizedEmail)
@@ -29,6 +28,7 @@
     const membershipExists = await checkMembershipExists(
       existingUser.id,
       org.id,
+      client,
     );
 
     if (membershipExists) {
@@ -36,7 +36,7 @@
     }
   }
 
-  const { data: existingInvitation } = await supabase
+  const { data: existingInvitation } = await client
     .from("invitations")
     .select("id, expires_at")
     .eq("org_id", org.id)
@@ -52,7 +52,7 @@
 
   const invitationId = uuid4();
 
-  const { data: invitation, error } = await supabase
+  const { data: invitation, error } = await client
     .from("invitations")
     .insert({
       id: invitationId,

revokeInvitation (+5/-7)

Location: invitation.ts:231organization/invitation/mutations.ts:127

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/mutations.ts	NEW
@@ -1,26 +1,24 @@
 revokeInvitation: async (
   _: unknown,
-  args: { input: { invitationId: string } },
+  args: MutationRevokeInvitationArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const input = validateInput(RevokeInvitationSchema, args.input);
 
-  const supabase = createAdminClient();
+  const { client } = await getOrgScopedClient(context, input.orgId);
 
-  const { data: invitation, error: invError } = await supabase
+  const { data: invitation, error: invError } = await client
     .from("invitations")
     .select("*")
     .eq("id", input.invitationId)
+    .eq("org_id", input.orgId)
     .single();
 
   if (invError || !invitation) {
     throw InvitationErrors.notFound();
   }
 
-  await requireOrgMembership(authenticatedUser.userId, invitation.org_id);
-
-  const { error } = await supabase
+  const { error } = await client
     .from("invitations")
     .update({ deleted_at: new Date().toISOString() })
     .eq("id", input.invitationId);

orgId (+1/-1)

Location: invitation.ts:272organization/invitation/type-resolvers.ts:16

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: InvitationsRow) => parent.org_id;

status (+1/-5)

Location: invitation.ts:274organization/invitation/type-resolvers.ts:18

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/type-resolvers.ts	NEW
@@ -1,8 +1,4 @@
-status: (parent: {
-  accepted_at: string | null;
-  deleted_at: string | null;
-  expires_at: string;
-}) => {
+status: (parent: InvitationsRow) => {
   if (parent.deleted_at) return "REVOKED";
   if (parent.accepted_at) return "ACCEPTED";
   if (new Date(parent.expires_at) < new Date()) return "EXPIRED";

createdAt (+1/-1)

Location: invitation.ts:285organization/invitation/type-resolvers.ts:25

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-createdAt: (parent: { created_at: string }) => parent.created_at;
+createdAt: (parent: InvitationsRow) => parent.created_at;

expiresAt (+1/-1)

Location: invitation.ts:286organization/invitation/type-resolvers.ts:26

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-expiresAt: (parent: { expires_at: string }) => parent.expires_at;
+expiresAt: (parent: InvitationsRow) => parent.expires_at;

acceptedAt (+1/-1)

Location: invitation.ts:287organization/invitation/type-resolvers.ts:27

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-acceptedAt: (parent: { accepted_at: string | null }) => parent.accepted_at;
+acceptedAt: (parent: InvitationsRow) => parent.accepted_at;

deletedAt (+1/-1)

Location: invitation.ts:288organization/invitation/type-resolvers.ts:28

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-deletedAt: (parent: { deleted_at: string | null }) => parent.deleted_at;
+deletedAt: (parent: InvitationsRow) => parent.deleted_at;

organization (+7/-2)

Location: invitation.ts:290organization/invitation/type-resolvers.ts:30

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/type-resolvers.ts	NEW
@@ -1,3 +1,8 @@
-organization: async (parent: { org_id: string }) => {
-  return getOrganization(parent.org_id);
+organization: async (
+  parent: InvitationsRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgScopedClient(context, parent.org_id);
+  return getOrganization(parent.org_id, client);
 };

invitedBy (+7/-2)

Location: invitation.ts:294organization/invitation/type-resolvers.ts:39

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/type-resolvers.ts	NEW
@@ -1,3 +1,8 @@
-invitedBy: async (parent: { invited_by: string }) => {
-  return getUserProfile(parent.invited_by);
+invitedBy: async (
+  parent: InvitationsRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgScopedClient(context, parent.org_id);
+  return getUserProfile(parent.invited_by, client);
 };

acceptedBy (+7/-2)

Location: invitation.ts:298organization/invitation/type-resolvers.ts:48

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/type-resolvers.ts	NEW
@@ -1,4 +1,9 @@
-acceptedBy: async (parent: { accepted_by: string | null }) => {
+acceptedBy: async (
+  parent: InvitationsRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgScopedClient(context, parent.org_id);
   if (!parent.accepted_by) return null;
-  return getUserProfile(parent.accepted_by);
+  return getUserProfile(parent.accepted_by, client);
 };

userRole (+1/-2)

Location: invitation.ts:303organization/invitation/type-resolvers.ts:59

View Diff
===================================================================
--- invitation.ts	OLD
+++ organization/invitation/type-resolvers.ts	NEW
@@ -1,2 +1,1 @@
-userRole: (parent: { user_role: string | undefined }) =>
-  parent.user_role?.toUpperCase() || "admin".toUpperCase();
+userRole: () => "ADMIN";
notebook/ (1 functions)

createNotebook (+4/-6)

Location: notebook.ts:59organization/notebook/mutations.ts:18

View Diff
===================================================================
--- notebook.ts	OLD
+++ organization/notebook/mutations.ts	NEW
@@ -1,23 +1,21 @@
 createNotebook: async (
   _: unknown,
-  args: { input: { orgId: string; name: string; description?: string } },
+  args: MutationCreateNotebookArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const input = validateInput(CreateNotebookSchema, args.input);
 
-  const supabase = createAdminClient();
-  await requireOrganizationAccess(authenticatedUser.userId, input.orgId);
+  const { client, userId } = await getOrgScopedClient(context, input.orgId);
 
   const notebookId = uuidv4();
-  const { data: notebook, error } = await supabase
+  const { data: notebook, error } = await client
     .from("notebooks")
     .insert({
       id: notebookId,
       org_id: input.orgId,
       notebook_name: input.name,
       description: input.description,
-      created_by: authenticatedUser.userId,
+      created_by: userId,
     })
     .select()
     .single();
organization/ (16 functions)

addUserByEmail (+7/-11)

Location: organization.ts:61organization/organization/mutations.ts:24

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/mutations.ts	NEW
@@ -1,19 +1,15 @@
 addUserByEmail: async (
   _: unknown,
-  args: { input: { orgId: string; email: string; role: string } },
+  args: MutationAddUserByEmailArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const input = validateInput(AddUserByEmailSchema, args.input);
 
-  const supabase = createAdminClient();
-  const org = await getOrganization(input.orgId);
+  const { client } = await getOrgScopedClient(context, input.orgId);
 
-  await requireOrgMembership(authenticatedUser.userId, org.id);
-
   const normalizedEmail = input.email.toLowerCase().trim();
 
-  const { data: userProfile } = await supabase
+  const { data: userProfile } = await client
     .from("user_profiles")
     .select("id")
     .ilike("email", normalizedEmail)
@@ -23,11 +19,11 @@
     throw UserErrors.notFound();
   }
 
-  const { data: existingMember } = await supabase
+  const { data: existingMember } = await client
     .from("users_by_organization")
     .select("id")
     .eq("user_id", userProfile.id)
-    .eq("org_id", org.id)
+    .eq("org_id", input.orgId)
     .is("deleted_at", null)
     .single();
 
@@ -38,10 +34,10 @@
     );
   }
 
-  const { data: member, error } = await supabase
+  const { data: member, error } = await client
     .from("users_by_organization")
     .insert({
-      org_id: org.id,
+      org_id: input.orgId,
       user_id: userProfile.id,
       user_role: input.role.toLowerCase(),
     })

removeMember (+9/-9)

Location: organization.ts:124organization/organization/mutations.ts:83

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/mutations.ts	NEW
@@ -1,24 +1,24 @@
 removeMember: async (
   _: unknown,
-  args: { input: { orgId: string; userId: string } },
+  args: MutationRemoveMemberArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const input = validateInput(RemoveMemberSchema, args.input);
 
-  if (input.userId === authenticatedUser.userId) {
+  const { client, userId: authenticatedUserId } = await getOrgScopedClient(
+    context,
+    input.orgId,
+  );
+
+  if (input.userId === authenticatedUserId) {
     throw OrganizationErrors.cannotRemoveSelf();
   }
 
-  const supabase = createAdminClient();
-  const org = await getOrganization(input.orgId);
-  await requireOrgMembership(authenticatedUser.userId, org.id);
-
-  const { error } = await supabase
+  const { error } = await client
     .from("users_by_organization")
     .update({ deleted_at: new Date().toISOString() })
     .eq("user_id", input.userId)
-    .eq("org_id", org.id)
+    .eq("org_id", input.orgId)
     .is("deleted_at", null);
 
   if (error) {

updateMemberRole (+4/-6)

Location: organization.ts:159organization/organization/mutations.ts:118

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/mutations.ts	NEW
@@ -1,19 +1,17 @@
 updateMemberRole: async (
   _: unknown,
-  args: { input: { orgId: string; userId: string; role: string } },
+  args: MutationUpdateMemberRoleArgs,
   context: GraphQLContext,
 ) => {
-  requireAuthentication(context.user);
   const input = validateInput(UpdateMemberRoleSchema, args.input);
 
-  const supabase = createAdminClient();
-  const org = await getOrganization(input.orgId);
+  const { client } = await getOrgScopedClient(context, input.orgId);
 
-  const { data: member, error } = await supabase
+  const { data: member, error } = await client
     .from("users_by_organization")
     .update({ user_role: input.role.toLowerCase() })
     .eq("user_id", input.userId)
-    .eq("org_id", org.id)
+    .eq("org_id", input.orgId)
     .is("deleted_at", null)
     .select()
     .single();

name (+1/-1)

Location: organization.ts:194organization/organization/type-resolvers.ts:34

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-name: (parent: { org_name: string }) => parent.org_name;
+name: (parent: OrganizationsRow) => parent.org_name;

displayName (+1/-1)

Location: organization.ts:195organization/organization/type-resolvers.ts:35

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-displayName: (parent: { display_name: string | null }) => parent.display_name;
+displayName: (parent: OrganizationsRow) => parent.org_name;

createdAt (+1/-1)

Location: organization.ts:197organization/organization/type-resolvers.ts:36

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-createdAt: (parent: { created_at: string }) => parent.created_at;
+createdAt: (parent: OrganizationsRow) => parent.created_at;

updatedAt (+1/-1)

Location: organization.ts:198organization/organization/type-resolvers.ts:37

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-updatedAt: (parent: { updated_at: string }) => parent.updated_at;
+updatedAt: (parent: OrganizationsRow) => parent.updated_at;

members (+18/-16)

Location: organization.ts:200organization/organization/type-resolvers.ts:39

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,29 +1,31 @@
 members: async (
-  parent: { id: string },
+  parent: OrganizationsRow,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
-  await requireOrgMembership(authenticatedUser.userId, parent.id);
+  const { client } = await getOrgScopedClient(context, parent.id);
 
-  const supabase = createAdminClient();
+  let query = client
+    .from("users_by_organization")
+    .select("*, user_profiles(*)", { count: "exact" })
+    .eq("org_id", parent.id)
+    .is("deleted_at", null);
 
-  const { data: membersData, count } = await maybeAddQueryPagination(
-    supabase
-      .from("users_by_organization")
-      .select("*, user_profiles(*)", { count: "exact" })
-      .eq("org_id", parent.id)
-      .is("deleted_at", null),
-    args,
-  );
+  if (args.first) {
+    query = query.limit(args.first);
+  }
 
+  const { data: membersData, count } = await query;
+
   if (!membersData || membersData.length === 0) {
-    return buildConnectionOrEmpty(null, args, count);
+    return emptyConnection();
   }
 
   const users = membersData
-    .map((m) => m.user_profiles)
-    .filter((user) => user !== null);
+    .map((m: any) => m.user_profiles)
+    .filter(
+      (user: UserProfilesRow | null): user is UserProfilesRow => user !== null,
+    );
 
-  return buildConnectionOrEmpty(users, args, count);
+  return buildConnection(users, args, count ?? 0);
 };

notebooks (+9/-8)

Location: organization.ts:230organization/organization/type-resolvers.ts:72

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,19 +1,20 @@
 notebooks: async (
-  parent: { id: string },
+  parent: OrganizationsRow,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
-  await requireOrgMembership(authenticatedUser.userId, parent.id);
+  const { client, userId } = await getOrgScopedClient(context, parent.id);
+  const orgIds = await getUserOrganizationIds(userId, client);
 
-  return queryWithPagination(args, context, {
+  const options: ExplicitClientQueryOptions<"notebooks"> = {
+    client,
+    orgIds,
     tableName: "notebooks",
     whereSchema: NotebookWhereSchema,
-    requireAuth: false,
-    filterByUserOrgs: false,
-    parentOrgIds: parent.id,
     basePredicate: {
       is: [{ key: "deleted_at", value: null }],
     },
-  });
+  };
+
+  return queryWithPagination(args, context, options);
 };

datasets (+9/-8)

Location: organization.ts:250organization/organization/type-resolvers.ts:93

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,19 +1,20 @@
 datasets: async (
-  parent: { id: string },
+  parent: OrganizationsRow,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
-  await requireOrgMembership(authenticatedUser.userId, parent.id);
+  const { client, userId } = await getOrgScopedClient(context, parent.id);
+  const orgIds = await getUserOrganizationIds(userId, client);
 
-  return queryWithPagination(args, context, {
+  const options: ExplicitClientQueryOptions<"datasets"> = {
+    client,
+    orgIds,
     tableName: "datasets",
     whereSchema: DatasetWhereSchema,
-    requireAuth: false,
-    filterByUserOrgs: false,
-    parentOrgIds: parent.id,
     basePredicate: {
       is: [{ key: "deleted_at", value: null }],
     },
-  });
+  };
+
+  return queryWithPagination(args, context, options);
 };

dataConnections (+8/-7)

Location: organization.ts:270organization/organization/type-resolvers.ts:114

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -3,17 +3,18 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
-  await requireOrgMembership(authenticatedUser.userId, parent.id);
+  const { client, userId } = await getOrgScopedClient(context, parent.id);
+  const orgIds = await getUserOrganizationIds(userId, client);
 
-  return queryWithPagination(args, context, {
+  const options: ExplicitClientQueryOptions<"dynamic_connectors"> = {
+    client,
+    orgIds,
     tableName: "dynamic_connectors",
     whereSchema: DataConnectionWhereSchema,
-    requireAuth: false,
-    filterByUserOrgs: false,
-    parentOrgIds: parent.id,
     basePredicate: {
       is: [{ key: "deleted_at", value: null }],
     },
-  });
+  };
+
+  return queryWithPagination(args, context, options);
 };

userId (+1/-1)

Location: organization.ts:292organization/organization/type-resolvers.ts:137

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-userId: (parent: { user_id: string }) => parent.user_id;
+userId: (parent: UsersByOrganizationRow) => parent.user_id;

orgId (+1/-1)

Location: organization.ts:293organization/organization/type-resolvers.ts:138

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: UsersByOrganizationRow) => parent.org_id;

userRole (+1/-1)

Location: organization.ts:294organization/organization/type-resolvers.ts:139

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-userRole: (parent: { user_role: string }) => parent.user_role.toUpperCase();
+userRole: (parent: UsersByOrganizationRow) => parent.user_role.toUpperCase();

createdAt (+1/-1)

Location: organization.ts:295organization/organization/type-resolvers.ts:141

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-createdAt: (parent: { created_at: string }) => parent.created_at;
+createdAt: (parent: UsersByOrganizationRow) => parent.created_at;

user (+7/-2)

Location: organization.ts:297organization/organization/type-resolvers.ts:143

View Diff
===================================================================
--- organization.ts	OLD
+++ organization/organization/type-resolvers.ts	NEW
@@ -1,3 +1,8 @@
-user: async (parent: { user_id: string }) => {
-  return getUserProfile(parent.user_id);
+user: async (
+  parent: UsersByOrganizationRow,
+  _args,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgScopedClient(context, parent.org_id);
+  return getUserProfile(parent.user_id, client);
 };
static-model/ (1 functions)

createStaticModel (+4/-9)

Location: static-model.ts:57organization/static-model/mutations.ts:18

View Diff
===================================================================
--- static-model.ts	OLD
+++ organization/static-model/mutations.ts	NEW
@@ -1,18 +1,13 @@
 createStaticModel: async (
   _: unknown,
-  {
-    input,
-  }: {
-    input: z.infer<typeof CreateStaticModelSchema>;
-  },
+  { input }: MutationCreateStaticModelArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const validatedInput = validateInput(CreateStaticModelSchema, input);
-  await requireOrgMembership(authenticatedUser.userId, validatedInput.orgId);
 
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+  const { client } = await getOrgScopedClient(context, validatedInput.orgId);
+
+  const { data, error } = await client
     .from("static_model")
     .insert({
       org_id: validatedInput.orgId,
resource/ (87 functions)
data-connection/ (3 functions)

deleteDataConnection (+9/-17)

Location: data-connection.ts:172resource/data-connection/mutations.ts:92

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/mutations.ts	NEW
@@ -1,25 +1,17 @@
 deleteDataConnection: async (
   _: unknown,
-  { id }: { id: string },
+  { id }: MutationDeleteDataConnectionArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
-  const supabase = createAdminClient();
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_connection",
+    id,
+    "admin",
+  );
 
-  const { data: dataConnection, error: fetchError } = await supabase
+  const { data: connector, error: updateError } = await client
     .from("dynamic_connectors")
-    .select("org_id")
-    .eq("id", id)
-    .single();
-
-  if (fetchError || !dataConnection) {
-    throw ResourceErrors.notFound("DataConnection", id);
-  }
-
-  await requireOrgMembership(authenticatedUser.userId, dataConnection.org_id);
-
-  const { data: connector, error: updateError } = await supabase
-    .from("dynamic_connectors")
     .update({
       deleted_at: new Date().toISOString(),
       updated_at: new Date().toISOString(),
@@ -43,7 +35,7 @@
 
   if (trinoError) {
     // Best effort reverting operation
-    await supabase
+    await client
       .from("dynamic_connectors")
       .update({
         deleted_at: null,

syncDataConnection (+10/-6)

Location: data-connection.ts:238resource/data-connection/mutations.ts:147

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/mutations.ts	NEW
@@ -1,12 +1,18 @@
 syncDataConnection: async (
   _: unknown,
-  { id }: { id: string },
+  { id }: MutationSyncDataConnectionArgs,
   context: GraphQLContext,
 ) => {
   const authenticatedUser = requireAuthentication(context.user);
-  const supabase = createAdminClient();
 
-  const { data: dataConnection, error: fetchError } = await supabase
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_connection",
+    id,
+    "write",
+  );
+
+  const { data: dataConnection, error: fetchError } = await client
     .from("dynamic_connectors")
     .select("id, org_id")
     .eq("id", id)
@@ -16,10 +22,8 @@
     throw ResourceErrors.notFound("DataConnection", id);
   }
 
-  await requireOrgMembership(authenticatedUser.userId, dataConnection.org_id);
-
   const queuedRun = await syncDataConnection(
-    supabase,
+    client,
     authenticatedUser.userId,
     dataConnection,
   );

organization (+12/-2)

Location: data-connection.ts:277resource/data-connection/type-resolvers.ts:24

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW
@@ -1,3 +1,13 @@
-organization: (parent: DynamicConnectorsRow) => {
-  return getOrganization(parent.org_id);
+organization: async (
+  parent: DynamicConnectorsRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_connection",
+    parent.id,
+    "read",
+  );
+  return getOrganization(parent.org_id, client);
 };
data-ingestion/ (2 functions)

modelContext (+2/-0)

Location: data-ingestion.ts:120resource/data-ingestion/type-resolvers.ts:51

View Diff
===================================================================
--- data-ingestion.ts	OLD
+++ resource/data-ingestion/type-resolvers.ts	NEW
@@ -1,5 +1,7 @@
 modelContext: async (
   parent: DataIngestionsRow,
+  // TODO(jabolo): Find the correct type from @/lib/graphql/generated/graphql
+  // eslint-disable-next-line oso-frontend/type-safety/no-inline-resolver-types
   args: { tableName: string },
 ) => {
   return getModelContext(parent.dataset_id, args.tableName);

orgId (+11/-3)

Location: data-ingestion.ts:98resource/data-ingestion/type-resolvers.ts:21

View Diff
===================================================================
--- data-ingestion.ts	OLD
+++ resource/data-ingestion/type-resolvers.ts	NEW
@@ -1,6 +1,14 @@
-orgId: async (parent: DataIngestionsRow) => {
-  const supabase = createAdminClient();
-  const { data: dataset, error } = await supabase
+orgId: async (
+  parent: DataIngestionsRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_ingestion",
+    parent.id,
+  );
+  const { data: dataset, error } = await client
     .from("datasets")
     .select("org_id")
     .eq("id", parent.dataset_id)
data-model/ (35 functions)

updateDataModel (+8/-19)

Location: data-model.ts:97resource/data-model/mutations.ts:30

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/mutations.ts	NEW
@@ -1,28 +1,17 @@
 updateDataModel: async (
   _: unknown,
-  {
-    input,
-  }: {
-    input: z.infer<typeof UpdateDataModelSchema>;
-  },
+  { input }: MutationUpdateDataModelArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const validatedInput = validateInput(UpdateDataModelSchema, input);
-  const supabase = createAdminClient();
 
-  const { data: dataModel, error: dataModelError } = await supabase
-    .from("model")
-    .select("org_id")
-    .eq("id", validatedInput.dataModelId)
-    .single();
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    validatedInput.dataModelId,
+    "write",
+  );
 
-  if (dataModelError || !dataModel) {
-    throw ResourceErrors.notFound("DataModel", validatedInput.dataModelId);
-  }
-
-  await requireOrgMembership(authenticatedUser.userId, dataModel.org_id);
-
   const updateData: ModelUpdate = {};
   if (validatedInput.name !== undefined) {
     updateData.name = validatedInput.name;
@@ -34,7 +23,7 @@
     updateData.updated_at = new Date().toISOString();
   }
 
-  const { data, error } = await supabase
+  const { data, error } = await client
     .from("model")
     .update(updateData)
     .eq("id", validatedInput.dataModelId)

createDataModelRevision (+11/-8)

Location: data-model.ts:151resource/data-model/mutations.ts:74

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/mutations.ts	NEW
@@ -1,13 +1,18 @@
 createDataModelRevision: async (
   _: unknown,
-  { input }: { input: z.infer<typeof CreateDataModelRevisionSchema> },
+  { input }: MutationCreateDataModelRevisionArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const validatedInput = validateInput(CreateDataModelRevisionSchema, input);
-  const supabase = createAdminClient();
 
-  const { data: dataModel, error: dataModelError } = await supabase
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    validatedInput.dataModelId,
+    "write",
+  );
+
+  const { data: dataModel, error: dataModelError } = await client
     .from("model")
     .select("org_id")
     .eq("id", validatedInput.dataModelId)
@@ -17,9 +22,7 @@
     throw ResourceErrors.notFound("DataModel", validatedInput.dataModelId);
   }
 
-  await requireOrgMembership(authenticatedUser.userId, dataModel.org_id);
-
-  const { data: latestRevision } = await supabase
+  const { data: latestRevision } = await client
     .from("model_revision")
     .select("*")
     .eq("model_id", validatedInput.dataModelId)
@@ -45,7 +48,7 @@
 
   const revisionNumber = (latestRevision?.revision_number || 0) + 1;
 
-  const { data, error } = await supabase
+  const { data, error } = await client
     .from("model_revision")
     .insert({
       org_id: dataModel.org_id,

createDataModelRelease (+11/-8)

Location: data-model.ts:270resource/data-model/mutations.ts:197

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/mutations.ts	NEW
@@ -1,13 +1,18 @@
 createDataModelRelease: async (
   _: unknown,
-  { input }: { input: z.infer<typeof CreateDataModelReleaseSchema> },
+  { input }: MutationCreateDataModelReleaseArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const validatedInput = validateInput(CreateDataModelReleaseSchema, input);
-  const supabase = createAdminClient();
 
-  const { data: dataModel, error: dataModelError } = await supabase
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    validatedInput.dataModelId,
+    "write",
+  );
+
+  const { data: dataModel, error: dataModelError } = await client
     .from("model")
     .select("org_id")
     .eq("id", validatedInput.dataModelId)
@@ -17,9 +22,7 @@
     throw ResourceErrors.notFound("DataModel", validatedInput.dataModelId);
   }
 
-  await requireOrgMembership(authenticatedUser.userId, dataModel.org_id);
-
-  const { error: revisionError } = await supabase
+  const { error: revisionError } = await client
     .from("model_revision")
     .select("id")
     .eq("id", validatedInput.dataModelRevisionId)
@@ -33,7 +36,7 @@
     );
   }
 
-  const { data, error } = await supabase
+  const { data, error } = await client
     .from("model_release")
     .upsert({
       org_id: dataModel.org_id,

deleteDataModel (+8/-16)

Location: data-model.ts:327resource/data-model/mutations.ts:258

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/mutations.ts	NEW
@@ -1,25 +1,17 @@
 deleteDataModel: async (
   _: unknown,
-  { id }: { id: string },
+  { id }: MutationDeleteDataModelArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
-  const supabase = createAdminClient();
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    id,
+    "admin",
+  );
 
-  const { data: dataModel, error: fetchError } = await supabase
+  const { error } = await client
     .from("model")
-    .select("org_id")
-    .eq("id", id)
-    .single();
-
-  if (fetchError || !dataModel) {
-    throw ResourceErrors.notFound("DataModel", id);
-  }
-
-  await requireOrgMembership(authenticatedUser.userId, dataModel.org_id);
-
-  const { error } = await supabase
-    .from("model")
     .update({ deleted_at: new Date().toISOString() })
     .eq("id", id);
 

orgId (+1/-1)

Location: data-model.ts:365resource/data-model/type-resolvers.ts:35

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: ModelRow) => parent.org_id;

organization (+11/-2)

Location: data-model.ts:366resource/data-model/type-resolvers.ts:36

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,3 +1,12 @@
-organization: (parent: { org_id: string }) => {
-  return getOrganization(parent.org_id);
+organization: async (
+  parent: ModelRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.id,
+  );
+  return getOrganization(parent.org_id, client);
 };

dataset (+14/-6)

Location: data-model.ts:369resource/data-model/type-resolvers.ts:48

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,7 +1,15 @@
-dataset: (parent: { dataset_id: string }) => {
-  return getResourceById({
-    tableName: "datasets",
-    id: parent.dataset_id,
-    userId: "",
-  });
+dataset: async (parent: ModelRow, _args: unknown, context: GraphQLContext) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.id,
+  );
+  return getResourceById(
+    {
+      tableName: "datasets",
+      id: parent.dataset_id,
+      userId: "",
+    },
+    client,
+  );
 };

revisions (+12/-1)

Location: data-model.ts:376resource/data-model/type-resolvers.ts:67

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,8 +1,19 @@
 revisions: async (
-  parent: { id: string; org_id: string },
+  parent: ModelRow,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
+  // TODO(jabolo): Handle special case where the caller does
+  // not pass `orgIds` as `system`. In the new implementation,
+  // it will fail and return and empty connection as of now.
+  const { client: _client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.id,
+    "read",
+  );
+
+  // eslint-disable-next-line @typescript-eslint/no-deprecated
   return queryWithPagination(args, context, {
     tableName: "model_revision",
     whereSchema: DataModelRevisionWhereSchema,

releases (+12/-1)

Location: data-model.ts:392resource/data-model/type-resolvers.ts:94

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,8 +1,19 @@
 releases: async (
-  parent: { id: string; org_id: string },
+  parent: ModelRow,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
+  // TODO(jabolo): Handle special case where the caller does
+  // not pass `orgIds` as `system`. In the new implementation,
+  // it will fail and return and empty connection as of now.
+  const { client: _client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.id,
+    "read",
+  );
+
+  // eslint-disable-next-line @typescript-eslint/no-deprecated
   return queryWithPagination(args, context, {
     tableName: "model_release",
     whereSchema: DataModelReleaseWhereSchema,

isEnabled (+1/-1)

Location: data-model.ts:412resource/data-model/type-resolvers.ts:125

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-isEnabled: (parent: { is_enabled: boolean }) => parent.is_enabled;
+isEnabled: (parent: ModelRow) => parent.is_enabled;

createdAt (+1/-1)

Location: data-model.ts:413resource/data-model/type-resolvers.ts:126

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-createdAt: (parent: { created_at: string }) => parent.created_at;
+createdAt: (parent: ModelRow) => parent.created_at;

updatedAt (+1/-1)

Location: data-model.ts:414resource/data-model/type-resolvers.ts:127

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-updatedAt: (parent: { updated_at: string }) => parent.updated_at;
+updatedAt: (parent: ModelRow) => parent.updated_at;

latestRevision (+11/-3)

Location: data-model.ts:415resource/data-model/type-resolvers.ts:128

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,6 +1,14 @@
-latestRevision: async (parent: { id: string }) => {
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+latestRevision: async (
+  parent: ModelRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.id,
+  );
+  const { data, error } = await client
     .from("model_revision")
     .select("*")
     .eq("model_id", parent.id)

latestRelease (+11/-3)

Location: data-model.ts:430resource/data-model/type-resolvers.ts:151

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,6 +1,14 @@
-latestRelease: async (parent: { id: string }) => {
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+latestRelease: async (
+  parent: ModelRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.id,
+  );
+  const { data, error } = await client
     .from("model_release")
     .select("*")
     .eq("model_id", parent.id)

runs (+11/-2)

Location: data-model.ts:446resource/data-model/type-resolvers.ts:175

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,3 +1,12 @@
-runs: async (parent: ModelRow, args: ConnectionArgs) => {
-  return getModelRunConnection(parent.dataset_id, parent.id, args);
+runs: async (
+  parent: ModelRow,
+  args: ConnectionArgs,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.id,
+  );
+  return getModelRunConnection(parent.dataset_id, parent.id, args, client);
 };

orgId (+1/-1)

Location: data-model.ts:468resource/data-model/type-resolvers.ts:206

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: ModelRevisionRow) => parent.org_id;

dataModelId (+1/-1)

Location: data-model.ts:469resource/data-model/type-resolvers.ts:207

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-dataModelId: (parent: { model_id: string }) => parent.model_id;
+dataModelId: (parent: ModelRevisionRow) => parent.model_id;

dataModel (+11/-3)

Location: data-model.ts:470resource/data-model/type-resolvers.ts:208

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,6 +1,14 @@
-dataModel: async (parent: { model_id: string }) => {
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+dataModel: async (
+  parent: ModelRevisionRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.model_id,
+  );
+  const { data, error } = await client
     .from("model")
     .select("*")
     .eq("id", parent.model_id)

organization (+11/-2)

Location: data-model.ts:482resource/data-model/type-resolvers.ts:228

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,3 +1,12 @@
-organization: (parent: { org_id: string }) => {
-  return getOrganization(parent.org_id);
+organization: async (
+  parent: ModelRevisionRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.model_id,
+  );
+  return getOrganization(parent.org_id, client);
 };

revisionNumber (+1/-1)

Location: data-model.ts:485resource/data-model/type-resolvers.ts:240

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-revisionNumber: (parent: { revision_number: number }) => parent.revision_number;
+revisionNumber: (parent: ModelRevisionRow) => parent.revision_number;

start (+1/-1)

Location: data-model.ts:487resource/data-model/type-resolvers.ts:241

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-start: (parent: { start: string | null }) => parent.start;
+start: (parent: ModelRevisionRow) => parent.start;

end (+1/-1)

Location: data-model.ts:488resource/data-model/type-resolvers.ts:242

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-end: (parent: { end: string | null }) => parent.end;
+end: (parent: ModelRevisionRow) => parent.end;

dependsOn (+1/-1)

Location: data-model.ts:489resource/data-model/type-resolvers.ts:243

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-dependsOn: (parent: { depends_on: unknown[] }) => parent.depends_on;
+dependsOn: (parent: ModelRevisionRow) => parent.depends_on;

partitionedBy (+1/-1)

Location: data-model.ts:490resource/data-model/type-resolvers.ts:244

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-partitionedBy: (parent: { partitioned_by: string[] }) => parent.partitioned_by;
+partitionedBy: (parent: ModelRevisionRow) => parent.partitioned_by;

clusteredBy (+1/-1)

Location: data-model.ts:492resource/data-model/type-resolvers.ts:245

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-clusteredBy: (parent: { clustered_by: string[] }) => parent.clustered_by;
+clusteredBy: (parent: ModelRevisionRow) => parent.clustered_by;

kindOptions (+1/-1)

Location: data-model.ts:493resource/data-model/type-resolvers.ts:246

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-kindOptions: (parent: { kind_options: unknown }) => parent.kind_options;
+kindOptions: (parent: ModelRevisionRow) => parent.kind_options;

createdAt (+1/-1)

Location: data-model.ts:494resource/data-model/type-resolvers.ts:247

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-createdAt: (parent: { created_at: string }) => parent.created_at;
+createdAt: (parent: ModelRevisionRow) => parent.created_at;

orgId (+1/-1)

Location: data-model.ts:498resource/data-model/type-resolvers.ts:251

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: ModelReleaseRow) => parent.org_id;

dataModelId (+1/-1)

Location: data-model.ts:499resource/data-model/type-resolvers.ts:252

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-dataModelId: (parent: { model_id: string }) => parent.model_id;
+dataModelId: (parent: ModelReleaseRow) => parent.model_id;

revisionId (+1/-1)

Location: data-model.ts:500resource/data-model/type-resolvers.ts:253

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-revisionId: (parent: { model_revision_id: string }) => parent.model_revision_id;
+revisionId: (parent: ModelReleaseRow) => parent.model_revision_id;

dataModel (+11/-3)

Location: data-model.ts:502resource/data-model/type-resolvers.ts:254

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,6 +1,14 @@
-dataModel: async (parent: { model_id: string }) => {
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+dataModel: async (
+  parent: ModelReleaseRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.model_id,
+  );
+  const { data, error } = await client
     .from("model")
     .select("*")
     .eq("id", parent.model_id)

revision (+11/-3)

Location: data-model.ts:514resource/data-model/type-resolvers.ts:274

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,6 +1,14 @@
-revision: async (parent: { model_revision_id: string }) => {
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+revision: async (
+  parent: ModelReleaseRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.model_id,
+  );
+  const { data, error } = await client
     .from("model_revision")
     .select("*")
     .eq("id", parent.model_revision_id)

organization (+11/-2)

Location: data-model.ts:529resource/data-model/type-resolvers.ts:297

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,3 +1,12 @@
-organization: (parent: { org_id: string }) => {
-  return getOrganization(parent.org_id);
+organization: async (
+  parent: ModelReleaseRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "data_model",
+    parent.model_id,
+  );
+  return getOrganization(parent.org_id, client);
 };

createdAt (+1/-1)

Location: data-model.ts:532resource/data-model/type-resolvers.ts:309

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-createdAt: (parent: { created_at: string }) => parent.created_at;
+createdAt: (parent: ModelReleaseRow) => parent.created_at;

updatedAt (+1/-1)

Location: data-model.ts:533resource/data-model/type-resolvers.ts:310

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-updatedAt: (parent: { updated_at: string }) => parent.updated_at;
+updatedAt: (parent: ModelReleaseRow) => parent.updated_at;
dataset/ (28 functions)

updateDataset (+8/-24)

Location: dataset.ts:101resource/dataset/mutations.ts:20

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/mutations.ts	NEW
@@ -1,35 +1,19 @@
 updateDataset: async (
   _: unknown,
-  args: {
-    input: {
-      id: string;
-      name?: string;
-      displayName?: string;
-      description?: string;
-      isPublic?: boolean;
-    };
-  },
+  args: MutationUpdateDatasetArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const input = validateInput(UpdateDatasetSchema, args.input);
 
-  const supabase = createAdminClient();
+  const { client } = await getOrgResourceClient(
+    context,
+    "dataset",
+    input.id,
+    "write",
+  );
 
-  const { data: existingDataset, error: existingError } = await supabase
+  const { data, error } = await client
     .from("datasets")
-    .select("org_id")
-    .eq("id", input.id)
-    .single();
-
-  if (existingError || !existingDataset) {
-    throw DatasetErrors.notFound();
-  }
-
-  await requireOrgMembership(authenticatedUser.userId, existingDataset.org_id);
-
-  const { data, error } = await supabase
-    .from("datasets")
     .update({
       name: input.name,
       display_name: input.displayName,

deleteDataset (+8/-16)

Location: dataset.ts:159resource/dataset/mutations.ts:59

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/mutations.ts	NEW
@@ -1,25 +1,17 @@
 deleteDataset: async (
   _: unknown,
-  { id }: { id: string },
+  { id }: MutationDeleteDatasetArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
-  const supabase = createAdminClient();
+  const { client } = await getOrgResourceClient(
+    context,
+    "dataset",
+    id,
+    "admin",
+  );
 
-  const { data: dataset, error: fetchError } = await supabase
+  const { error } = await client
     .from("datasets")
-    .select("org_id")
-    .eq("id", id)
-    .single();
-
-  if (fetchError || !dataset) {
-    throw DatasetErrors.notFound();
-  }
-
-  await requireOrgMembership(authenticatedUser.userId, dataset.org_id);
-
-  const { error } = await supabase
-    .from("datasets")
     .update({ deleted_at: new Date().toISOString() })
     .eq("id", id);
 

displayName (+1/-1)

Location: dataset.ts:198resource/dataset/type-resolvers.ts:41

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-displayName: (parent: { display_name: string | null }) => parent.display_name;
+displayName: (parent: DatasetsRow) => parent.display_name;

createdAt (+1/-1)

Location: dataset.ts:200resource/dataset/type-resolvers.ts:42

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-createdAt: (parent: { created_at: string }) => parent.created_at;
+createdAt: (parent: DatasetsRow) => parent.created_at;

updatedAt (+1/-1)

Location: dataset.ts:201resource/dataset/type-resolvers.ts:43

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-updatedAt: (parent: { updated_at: string }) => parent.updated_at;
+updatedAt: (parent: DatasetsRow) => parent.updated_at;

creatorId (+1/-1)

Location: dataset.ts:202resource/dataset/type-resolvers.ts:44

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-creatorId: (parent: { created_by: string }) => parent.created_by;
+creatorId: (parent: DatasetsRow) => parent.created_by;

orgId (+1/-1)

Location: dataset.ts:203resource/dataset/type-resolvers.ts:45

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: DatasetsRow) => parent.org_id;

isPublic (+1/-1)

Location: dataset.ts:204resource/dataset/type-resolvers.ts:46

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-isPublic: (parent: { is_public: boolean }) => parent.is_public;
+isPublic: (parent: DatasetsRow) => parent.is_public;

type (+1/-1)

Location: dataset.ts:205resource/dataset/type-resolvers.ts:47

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-type: (parent: { dataset_type: string }) => parent.dataset_type;
+type: (parent: DatasetsRow) => parent.dataset_type;

creator (+7/-2)

Location: dataset.ts:207resource/dataset/type-resolvers.ts:49

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,3 +1,8 @@
-creator: async (parent: { created_by: string }) => {
-  return getUserProfile(parent.created_by);
+creator: async (
+  parent: DatasetsRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(context, "dataset", parent.id);
+  return getUserProfile(parent.created_by, client);
 };

organization (+7/-2)

Location: dataset.ts:211resource/dataset/type-resolvers.ts:62

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,3 +1,8 @@
-organization: async (parent: { org_id: string }) => {
-  return getOrganization(parent.org_id);
+organization: async (
+  parent: DatasetsRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(context, "dataset", parent.id);
+  return getOrganization(parent.org_id, client);
 };

typeDefinition (+3/-5)

Location: dataset.ts:214resource/dataset/type-resolvers.ts:75

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -21,11 +21,9 @@
       };
     }
     case "DATA_CONNECTION":
-      return {
-        __typename: "DataConnectionDefinition",
-        org_id: parent.org_id,
-        dataset_id: parent.id,
-      };
+      throw new Error(
+        `Dataset type "${parent.dataset_type}" is not supported yet.`,
+      );
     default:
       assertNever(
         parent.dataset_type,

tables (+46/-23)

Location: dataset.ts:250resource/dataset/type-resolvers.ts:109

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -5,6 +5,17 @@
 ) => {
   switch (parent.dataset_type) {
     case "USER_MODEL": {
+      // TODO(jabolo): Handle special case where the caller does
+      // not pass `orgIds` as `system`. In the new implementation,
+      // it will fail and return and empty connection as of now.
+      const { client: _client } = await getOrgResourceClient(
+        context,
+        "dataset",
+        parent.id,
+        "read",
+      );
+
+      // eslint-disable-next-line @typescript-eslint/no-deprecated
       return queryWithPagination(args, context, {
         tableName: "model",
         whereSchema: DataModelWhereSchema,
@@ -17,7 +28,18 @@
         },
       });
     }
-    case "STATIC_MODEL":
+    case "STATIC_MODEL": {
+      // TODO(jabolo): Handle special case where the caller does
+      // not pass `orgIds` as `system`. In the new implementation,
+      // it will fail and return and empty connection as of now.
+      const { client: _client } = await getOrgResourceClient(
+        context,
+        "dataset",
+        parent.id,
+        "read",
+      );
+
+      // eslint-disable-next-line @typescript-eslint/no-deprecated
       return queryWithPagination(args, context, {
         tableName: "static_model",
         whereSchema: StaticModelWhereSchema,
@@ -29,7 +51,19 @@
           eq: [{ key: "dataset_id", value: parent.id }],
         },
       });
+    }
     case "DATA_INGESTION": {
+      // TODO(jabolo): Handle special case where the caller does
+      // not pass `orgIds` as `system`. In the new implementation,
+      // it will fail and return and empty connection as of now.
+      const { client: _client } = await getOrgResourceClient(
+        context,
+        "dataset",
+        parent.id,
+        "read",
+      );
+
+      // eslint-disable-next-line @typescript-eslint/no-deprecated
       const result = (await queryWithPagination(args, context, {
         tableName: "data_ingestion_as_table",
         whereSchema: DataIngestionsWhereSchema,
@@ -53,30 +87,19 @@
         })),
       };
     }
-    case "DATA_CONNECTION": {
-      const result = (await queryWithPagination(args, context, {
-        tableName: "data_connection_as_table",
-        whereSchema: DataConnectionWhereSchema,
-        requireAuth: false,
-        filterByUserOrgs: false,
-        parentOrgIds: parent.org_id,
-        basePredicate: {
-          eq: [{ key: "dataset_id", value: parent.id }],
+    case "DATA_CONNECTION":
+      // Table metadata is not available until after the ingestion job completes
+      // Tables are created dynamically during ingestion
+      return {
+        edges: [],
+        pageInfo: {
+          hasNextPage: false,
+          hasPreviousPage: false,
+          startCursor: null,
+          endCursor: null,
         },
-      })) as Connection<DataConnectionAsTableRow>;
-
-      return {
-        ...result,
-        edges: result.edges.map((edge) => ({
-          node: {
-            id: edge.node.table_id,
-            name: edge.node.table_name,
-            datasetId: edge.node.dataset_id,
-          },
-          cursor: edge.cursor,
-        })),
+        totalCount: 0,
       };
-    }
     default:
       assertNever(
         parent.dataset_type,

runs (+11/-1)

Location: dataset.ts:337resource/dataset/type-resolvers.ts:219

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,8 +1,18 @@
 runs: async (
-  parent: { id: string; org_id: string },
+  parent: DatasetsRow,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
+  // TODO(jabolo): Handle special case where the caller does
+  // not pass `orgIds` as `system`. In the new implementation,
+  // it will fail and return and empty connection as of now.
+  const { client: _client } = await getOrgResourceClient(
+    context,
+    "dataset",
+    parent.id,
+  );
+
+  // eslint-disable-next-line @typescript-eslint/no-deprecated
   return queryWithPagination(args, context, {
     tableName: "run",
     whereSchema: RunWhereSchema,

materializations (+12/-1)

Location: dataset.ts:358resource/dataset/type-resolvers.ts:250

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,8 +1,19 @@
 materializations: async (
-  parent: { id: string; org_id: string },
+  parent: DatasetsRow,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
+  // TODO(jabolo): Handle special case where the caller does
+  // not pass `orgIds` as `system`. In the new implementation,
+  // it will fail and return and empty connection as of now.
+  const { client: _client } = await getOrgResourceClient(
+    context,
+    "dataset",
+    parent.id,
+    "read",
+  );
+
+  // eslint-disable-next-line @typescript-eslint/no-deprecated
   return queryWithPagination(args, context, {
     tableName: "materialization",
     whereSchema: MaterializationWhereSchema,

orgId (+1/-1)

Location: dataset.ts:381resource/dataset/type-resolvers.ts:284

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: DatasetsRow) => parent.org_id;

datasetId (+1/-1)

Location: dataset.ts:382resource/dataset/type-resolvers.ts:285

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-datasetId: (parent: { dataset_id: string }) => parent.dataset_id;
+datasetId: (parent: DataModelDefinitionParent) => parent.dataset_id;

dataModels (+12/-1)

Location: dataset.ts:383resource/dataset/type-resolvers.ts:286

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,8 +1,19 @@
 dataModels: async (
-  parent: { dataset_id: string; org_id: string },
+  parent: DataModelDefinitionParent,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
+  // TODO(jabolo): Handle special case where the caller does
+  // not pass `orgIds` as `system`. In the new implementation,
+  // it will fail and return and empty connection as of now.
+  const { client: _client } = await getOrgResourceClient(
+    context,
+    "dataset",
+    parent.dataset_id,
+    "read",
+  );
+
+  // eslint-disable-next-line @typescript-eslint/no-deprecated
   return queryWithPagination(args, context, {
     tableName: "model",
     whereSchema: DataModelWhereSchema,

orgId (+1/-1)

Location: dataset.ts:403resource/dataset/type-resolvers.ts:317

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: StaticModelDefinitionParent) => parent.org_id;

datasetId (+1/-1)

Location: dataset.ts:404resource/dataset/type-resolvers.ts:318

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-datasetId: (parent: { dataset_id: string }) => parent.dataset_id;
+datasetId: (parent: StaticModelDefinitionParent) => parent.dataset_id;

staticModels (+12/-1)

Location: dataset.ts:405resource/dataset/type-resolvers.ts:319

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,8 +1,19 @@
 staticModels: async (
-  parent: { dataset_id: string; org_id: string },
+  parent: StaticModelDefinitionParent,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
+  // TODO(jabolo): Handle special case where the caller does
+  // not pass `orgIds` as `system`. In the new implementation,
+  // it will fail and return and empty connection as of now.
+  const { client: _client } = await getOrgResourceClient(
+    context,
+    "dataset",
+    parent.dataset_id,
+    "read",
+  );
+
+  // eslint-disable-next-line @typescript-eslint/no-deprecated
   return queryWithPagination(args, context, {
     tableName: "static_model",
     whereSchema: StaticModelWhereSchema,

orgId (+1/-1)

Location: dataset.ts:425resource/dataset/type-resolvers.ts:350

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: DataIngestionDefinitionParent) => parent.org_id;

datasetId (+1/-1)

Location: dataset.ts:426resource/dataset/type-resolvers.ts:351

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-datasetId: (parent: { dataset_id: string }) => parent.dataset_id;
+datasetId: (parent: DataIngestionDefinitionParent) => parent.dataset_id;

dataIngestion (+8/-3)

Location: dataset.ts:427resource/dataset/type-resolvers.ts:352

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,10 +1,15 @@
 dataIngestion: async (
-  parent: { dataset_id: string; org_id: string },
+  parent: DataIngestionDefinitionParent,
   _args: Record<string, never>,
+  context: GraphQLContext,
 ) => {
-  const supabase = createAdminClient();
+  const { client } = await getOrgResourceClient(
+    context,
+    "dataset",
+    parent.dataset_id,
+  );
 
-  const { data: config } = await supabase
+  const { data: config } = await client
     .from("data_ingestions")
     .select("*")
     .eq("dataset_id", parent.dataset_id)

materializations (+1/-1)

Location: dataset.ts:442resource/dataset/type-resolvers.ts:372

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,5 +1,5 @@
 materializations: async (
-  parent: { dataset_id: string; org_id: string },
+  parent: DataIngestionDefinitionParent,
   args: FilterableConnectionArgs & { tableName: string },
   context: GraphQLContext,
 ) => {

orgId (+1/-1)

Location: dataset.ts:459resource/dataset/type-resolvers.ts:389

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: DataConnectionDefinitionParent) => parent.org_id;

datasetId (+1/-1)

Location: dataset.ts:460resource/dataset/type-resolvers.ts:390

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-datasetId: (parent: { dataset_id: string }) => parent.dataset_id;
+datasetId: (parent: DataConnectionDefinitionParent) => parent.dataset_id;

dataConnectionAlias (+11/-3)

Location: dataset.ts:461resource/dataset/type-resolvers.ts:391

View Diff
===================================================================
--- dataset.ts	OLD
+++ resource/dataset/type-resolvers.ts	NEW
@@ -1,7 +1,15 @@
-dataConnectionAlias: async (parent: { dataset_id: string }) => {
-  const supabase = createAdminClient();
+dataConnectionAlias: async (
+  parent: DataConnectionDefinitionParent,
+  _args: Record<string, never>,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "dataset",
+    parent.dataset_id,
+  );
 
-  const { data: alias } = await supabase
+  const { data: alias } = await client
     .from("data_connection_alias")
     .select("*")
     .eq("dataset_id", parent.dataset_id)
model-context/ (1 functions)

updateModelContext (+12/-9)

Location: model-context.ts:44resource/model-context/mutations.ts:23

View Diff
===================================================================
--- model-context.ts	OLD
+++ resource/model-context/mutations.ts	NEW
@@ -1,9 +1,8 @@
 updateModelContext: async (
   _: unknown,
-  { input }: { input: z.infer<typeof UpdateModelContextSchema> },
+  { input }: MutationUpdateModelContextArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const validatedInput = validateInput(UpdateModelContextSchema, input);
   const {
     datasetId,
@@ -12,9 +11,15 @@
     columnContext,
   } = validatedInput;
 
-  const supabase = createAdminClient();
+  const { client } = await getOrgResourceClient(
+    context,
+    "dataset",
+    datasetId,
+    "write",
+  );
+
   // Check access to dataset
-  const { data: dataset, error: datasetError } = await supabase
+  const { data: dataset, error: datasetError } = await client
     .from("datasets")
     .select("org_id, dataset_type")
     .eq("id", datasetId)
@@ -24,12 +29,10 @@
     throw ValidationErrors.invalidInput("datasetId", "Dataset not found");
   }
 
-  await requireOrgMembership(authenticatedUser.userId, dataset.org_id);
-
   const tableId = generateTableId(dataset.dataset_type, modelId);
 
   // Check if context exists
-  const { data: existingContext } = await supabase
+  const { data: existingContext } = await client
     .from("model_contexts")
     .select("id")
     .eq("dataset_id", datasetId)
@@ -50,7 +53,7 @@
   };
 
   if (existingContext) {
-    const result = await supabase
+    const result = await client
       .from("model_contexts")
       .update(payload)
       .eq("id", existingContext.id)
@@ -59,7 +62,7 @@
     upsertedData = result.data;
     upsertError = result.error;
   } else {
-    const result = await supabase
+    const result = await client
       .from("model_contexts")
       .insert(payload)
       .select()
notebook/ (12 functions)

updateNotebook (+8/-15)

Location: notebook.ts:96resource/notebook/mutations.ts:36

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/mutations.ts	NEW
@@ -1,24 +1,17 @@
 updateNotebook: async (
   _: unknown,
-  args: { input: { id: string; name?: string; description?: string } },
+  args: MutationUpdateNotebookArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const input = validateInput(UpdateNotebookSchema, args.input);
 
-  const supabase = createAdminClient();
-  const { data: notebook, error: fetchError } = await supabase
-    .from("notebooks")
-    .select("org_id")
-    .eq("id", input.id)
-    .single();
+  const { client } = await getOrgResourceClient(
+    context,
+    "notebook",
+    input.id,
+    "write",
+  );
 
-  if (fetchError || !notebook) {
-    throw NotebookErrors.notFound();
-  }
-
-  await requireOrgMembership(authenticatedUser.userId, notebook.org_id);
-
   const updateData: { notebook_name?: string; description?: string } = {};
   if (input.name !== undefined) {
     updateData.notebook_name = input.name;
@@ -27,7 +20,7 @@
     updateData.description = input.description;
   }
 
-  const { data: updated, error } = await supabase
+  const { data: updated, error } = await client
     .from("notebooks")
     .update(updateData)
     .eq("id", input.id)

saveNotebookPreview (+2/-14)

Location: notebook.ts:145resource/notebook/mutations.ts:78

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/mutations.ts	NEW
@@ -1,25 +1,13 @@
 saveNotebookPreview: async (
   _: unknown,
-  args: { input: { notebookId: string; preview: string } },
+  args: MutationSaveNotebookPreviewArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const input = validateInput(SaveNotebookPreviewSchema, args.input);
   validateBase64PngImage(input.preview);
 
-  const supabase = createAdminClient();
-  const { data: notebook } = await supabase
-    .from("notebooks")
-    .select("org_id")
-    .eq("id", input.notebookId)
-    .single();
+  await getOrgResourceClient(context, "notebook", input.notebookId, "write");
 
-  if (!notebook) {
-    throw NotebookErrors.notFound();
-  }
-
-  await requireOrgMembership(authenticatedUser.userId, notebook.org_id);
-
   try {
     logger.log(
       `Uploading notebook preview for ${input.notebookId} to bucket "${PREVIEWS_BUCKET}"`,

publishNotebook (+10/-9)

Location: notebook.ts:194resource/notebook/mutations.ts:120

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/mutations.ts	NEW
@@ -1,13 +1,19 @@
 publishNotebook: async (
   _: unknown,
-  args: { notebookId: string },
+  args: MutationPublishNotebookArgs,
   context: GraphQLContext,
 ) => {
   const authenticatedUser = requireAuthentication(context.user);
   const { notebookId } = args;
-  const supabase = createAdminClient();
 
-  const { data: notebook } = await supabase
+  const { client } = await getOrgResourceClient(
+    context,
+    "notebook",
+    notebookId,
+    "admin",
+  );
+
+  const { data: notebook } = await client
     .from("notebooks")
     .select("id, organizations!inner(id, org_name)")
     .eq("id", notebookId)
@@ -17,17 +23,12 @@
     throw NotebookErrors.notFound();
   }
 
-  await requireOrgMembership(
-    authenticatedUser.userId,
-    notebook.organizations.id,
-  );
-
   const osoToken = await signOsoJwt(authenticatedUser, {
     orgId: notebook.organizations.id,
     orgName: notebook.organizations.org_name,
   });
 
-  const { data: queuedRun, error: queuedRunError } = await supabase
+  const { data: queuedRun, error: queuedRunError } = await client
     .from("run")
     .insert({
       org_id: notebook.organizations.id,

unpublishNotebook (+10/-5)

Location: notebook.ts:271resource/notebook/mutations.ts:199

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/mutations.ts	NEW
@@ -1,14 +1,19 @@
 unpublishNotebook: async (
   _: unknown,
-  args: { notebookId: string },
+  args: MutationUnpublishNotebookArgs,
   context: GraphQLContext,
 ) => {
   const authenticatedUser = requireAuthentication(context.user);
   const { notebookId } = args;
 
-  const supabase = createAdminClient();
+  const { client } = await getOrgResourceClient(
+    context,
+    "notebook",
+    notebookId,
+    "admin",
+  );
 
-  const { data: publishedNotebook, error } = await supabase
+  const { data: publishedNotebook, error } = await client
     .from("published_notebooks")
     .select("*")
     .eq("notebook_id", notebookId)
@@ -17,14 +22,14 @@
     logger.log("Failed to find published notebook:", error);
     throw NotebookErrors.notFound();
   }
-  const { error: deleteError } = await supabase.storage
+  const { error: deleteError } = await client.storage
     .from("published-notebooks")
     .remove([publishedNotebook.data_path]);
   if (deleteError) {
     logger.log("Failed to delete notebook file:", deleteError);
     throw ServerErrors.database("Failed to delete notebook file");
   }
-  const { error: updateError } = await supabase
+  const { error: updateError } = await client
     .from("published_notebooks")
     .update({
       deleted_at: new Date().toISOString(),

name (+1/-1)

Location: notebook.ts:318resource/notebook/type-resolvers.ts:22

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-name: (parent: { notebook_name: string }) => parent.notebook_name;
+name: (parent: NotebooksRow) => parent.notebook_name;

createdAt (+1/-1)

Location: notebook.ts:319resource/notebook/type-resolvers.ts:23

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-createdAt: (parent: { created_at: string }) => parent.created_at;
+createdAt: (parent: NotebooksRow) => parent.created_at;

updatedAt (+1/-1)

Location: notebook.ts:320resource/notebook/type-resolvers.ts:24

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-updatedAt: (parent: { updated_at: string }) => parent.updated_at;
+updatedAt: (parent: NotebooksRow) => parent.updated_at;

creatorId (+1/-1)

Location: notebook.ts:321resource/notebook/type-resolvers.ts:25

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-creatorId: (parent: { created_by: string }) => parent.created_by;
+creatorId: (parent: NotebooksRow) => parent.created_by;

orgId (+1/-1)

Location: notebook.ts:322resource/notebook/type-resolvers.ts:26

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-orgId: (parent: { org_id: string }) => parent.org_id;
+orgId: (parent: NotebooksRow) => parent.org_id;

creator (+7/-2)

Location: notebook.ts:324resource/notebook/type-resolvers.ts:28

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/type-resolvers.ts	NEW
@@ -1,3 +1,8 @@
-creator: async (parent: { created_by: string }) => {
-  return getUserProfile(parent.created_by);
+creator: async (
+  parent: NotebooksRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(context, "notebook", parent.id);
+  return getUserProfile(parent.created_by, client);
 };

organization (+7/-2)

Location: notebook.ts:328resource/notebook/type-resolvers.ts:41

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/type-resolvers.ts	NEW
@@ -1,3 +1,8 @@
-organization: async (parent: { org_id: string }) => {
-  return getOrganization(parent.org_id);
+organization: async (
+  parent: NotebooksRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(context, "notebook", parent.id);
+  return getOrganization(parent.org_id, client);
 };

preview (+1/-1)

Location: notebook.ts:332resource/notebook/type-resolvers.ts:54

View Diff
===================================================================
--- notebook.ts	OLD
+++ resource/notebook/type-resolvers.ts	NEW
@@ -1,4 +1,4 @@
-preview: async (parent: { id: string }) => {
+preview: async (parent: NotebooksRow) => {
   try {
     const objectKey = `${parent.id}.png`;
     const signedUrl = await getPreviewSignedUrl(
static-model/ (6 functions)

updateStaticModel (+8/-19)

Location: static-model.ts:95resource/static-model/mutations.ts:30

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/mutations.ts	NEW
@@ -1,28 +1,17 @@
 updateStaticModel: async (
   _: unknown,
-  {
-    input,
-  }: {
-    input: z.infer<typeof UpdateStaticModelSchema>;
-  },
+  { input }: MutationUpdateStaticModelArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const validatedInput = validateInput(UpdateStaticModelSchema, input);
-  const supabase = createAdminClient();
 
-  const { data: dataModel, error: dataModelError } = await supabase
-    .from("static_model")
-    .select("org_id")
-    .eq("id", validatedInput.staticModelId)
-    .single();
+  const { client } = await getOrgResourceClient(
+    context,
+    "static_model",
+    validatedInput.staticModelId,
+    "write",
+  );
 
-  if (dataModelError || !dataModel) {
-    throw ResourceErrors.notFound("StaticModel", validatedInput.staticModelId);
-  }
-
-  await requireOrgMembership(authenticatedUser.userId, dataModel.org_id);
-
   const updateData: StaticModelUpdate = {};
   if (validatedInput.name !== undefined) {
     updateData.name = validatedInput.name;
@@ -31,7 +20,7 @@
     updateData.updated_at = new Date().toISOString();
   }
 
-  const { data, error } = await supabase
+  const { data, error } = await client
     .from("static_model")
     .update(updateData)
     .eq("id", validatedInput.staticModelId)

createStaticModelUploadUrl (+8/-6)

Location: static-model.ts:149resource/static-model/mutations.ts:71

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/mutations.ts	NEW
@@ -1,12 +1,16 @@
 createStaticModelUploadUrl: async (
   _: unknown,
-  { staticModelId }: { staticModelId: string },
+  { staticModelId }: MutationCreateStaticModelUploadUrlArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
-  const supabase = createAdminClient();
+  const { client } = await getOrgResourceClient(
+    context,
+    "static_model",
+    staticModelId,
+    "write",
+  );
 
-  const { data: staticModel, error: staticModelError } = await supabase
+  const { data: staticModel, error: staticModelError } = await client
     .from("static_model")
     .select("org_id, dataset_id")
     .eq("id", staticModelId)
@@ -16,8 +20,6 @@
     throw ResourceErrors.notFound("StaticModel", staticModelId);
   }
 
-  await requireOrgMembership(authenticatedUser.userId, staticModel.org_id);
-
   const presignedUrl = await putSignedUrl(
     FILES_BUCKET,
     `${staticModel.dataset_id}/${staticModelId}`,

deleteStaticModel (+8/-16)

Location: static-model.ts:177resource/static-model/mutations.ts:102

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/mutations.ts	NEW
@@ -1,25 +1,17 @@
 deleteStaticModel: async (
   _: unknown,
-  { id }: { id: string },
+  { id }: MutationDeleteStaticModelArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
-  const supabase = createAdminClient();
+  const { client } = await getOrgResourceClient(
+    context,
+    "static_model",
+    id,
+    "admin",
+  );
 
-  const { data: staticModel, error: fetchError } = await supabase
+  const { error } = await client
     .from("static_model")
-    .select("org_id")
-    .eq("id", id)
-    .single();
-
-  if (fetchError || !staticModel) {
-    throw ResourceErrors.notFound("StaticModel", id);
-  }
-
-  await requireOrgMembership(authenticatedUser.userId, staticModel.org_id);
-
-  const { error } = await supabase
-    .from("static_model")
     .update({ deleted_at: new Date().toISOString() })
     .eq("id", id);
 

organization (+11/-2)

Location: static-model.ts:218resource/static-model/type-resolvers.ts:28

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/type-resolvers.ts	NEW
@@ -1,3 +1,12 @@
-organization: (parent: StaticModelRow) => {
-  return getOrganization(parent.org_id);
+organization: async (
+  parent: StaticModelRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "static_model",
+    parent.id,
+  );
+  return getOrganization(parent.org_id, client);
 };

dataset (+19/-7)

Location: static-model.ts:221resource/static-model/type-resolvers.ts:40

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/type-resolvers.ts	NEW
@@ -1,8 +1,20 @@
-dataset: (parent: StaticModelRow) => {
-  return getResourceById({
-    tableName: "datasets",
-    id: parent.dataset_id,
-    userId: "",
-    checkMembership: false,
-  });
+dataset: async (
+  parent: StaticModelRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "static_model",
+    parent.id,
+  );
+  return getResourceById(
+    {
+      tableName: "datasets",
+      id: parent.dataset_id,
+      userId: "",
+      checkMembership: false,
+    },
+    client,
+  );
 };

runs (+11/-2)

Location: static-model.ts:235resource/static-model/type-resolvers.ts:66

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/type-resolvers.ts	NEW
@@ -1,3 +1,12 @@
-runs: async (parent: StaticModelRow, args: ConnectionArgs) => {
-  return getModelRunConnection(parent.dataset_id, parent.id, args);
+runs: async (
+  parent: StaticModelRow,
+  args: ConnectionArgs,
+  context: GraphQLContext,
+) => {
+  const { client } = await getOrgResourceClient(
+    context,
+    "static_model",
+    parent.id,
+  );
+  return getModelRunConnection(parent.dataset_id, parent.id, args, client);
 };
system/ (10 functions)
run-type-resolvers.ts/ (4 functions)

dataset (+3/-3)

Location: scheduler.ts:272system/run-type-resolvers.ts:44

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW
@@ -1,9 +1,9 @@
-dataset: async (parent: RunRow) => {
+dataset: async (parent: RunRow, _args: unknown, context: GraphQLContext) => {
   if (!parent.dataset_id) {
     return null;
   }
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+  const client = getSystemClient(context);
+  const { data, error } = await client
     .from("datasets")
     .select("*")
     .eq("id", parent.dataset_id)

organization (+7/-3)

Location: scheduler.ts:293system/run-type-resolvers.ts:69

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW
@@ -1,6 +1,10 @@
-organization: async (parent: RunRow) => {
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+organization: async (
+  parent: RunRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const client = getSystemClient(context);
+  const { data, error } = await client
     .from("organizations")
     .select("*")
     .eq("id", parent.org_id)

steps (+6/-0)

Location: scheduler.ts:340system/run-type-resolvers.ts:120

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW
@@ -3,6 +3,12 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
+  // TODO(jabolo): Handle special case where the caller does
+  // not pass `orgIds` as `system`. In the new implementation,
+  // it will fail and return and empty connection as of now.
+  const _client = getSystemClient(context);
+
+  // eslint-disable-next-line @typescript-eslint/no-deprecated
   return queryWithPagination(args, context, {
     tableName: "step",
     whereSchema: StepWhereSchema,

requestedBy (+7/-2)

Location: scheduler.ts:356system/run-type-resolvers.ts:142

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW
@@ -1,6 +1,11 @@
-requestedBy: async (parent: RunRow) => {
+requestedBy: async (
+  parent: RunRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
   if (!parent.requested_by) {
     return null;
   }
-  return getUserProfile(parent.requested_by);
+  const client = getSystemClient(context);
+  return getUserProfile(parent.requested_by, client);
 };
system.ts/ (2 functions)

runs (+4/-0)

Location: scheduler.ts:190system/system.ts:15

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/system.ts	NEW
@@ -3,6 +3,10 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
+  // TODO(jabolo): How do we get user orgs from the system handler?
+  // Is it everything? How do we do it now?
+
+  // eslint-disable-next-line @typescript-eslint/no-deprecated
   return queryWithPagination(args, context, {
     tableName: "run",
     whereSchema: RunWhereSchema,

system (+2/-3)

Location: system.ts:724system/system.ts:9

View Diff
===================================================================
--- system.ts	OLD
+++ system/system.ts	NEW
@@ -1,6 +1,5 @@
 system: async (_: unknown, _args: unknown, context: GraphQLContext) => {
-  if (!context.systemCredentials) {
-    throw AuthenticationErrors.notAuthorized();
-  }
+  // TODO(jabolo): Check for perms manually here?
+  const _client = getSystemClient(context);
   return {};
 };
type-resolvers.ts/ (4 functions)

run (+7/-3)

Location: scheduler.ts:367system/type-resolvers.ts:89

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW
@@ -1,6 +1,10 @@
-run: async (parent: MaterializationRow) => {
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+run: async (
+  parent: MaterializationRow,
+  _args: unknown,
+  context: GraphQLContext,
+) => {
+  const client = getSystemClient(context);
+  const { data, error } = await client
     .from("run")
     .select("*")
     .eq("id", parent.run_id)

run (+3/-3)

Location: scheduler.ts:390system/type-resolvers.ts:117

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW
@@ -1,6 +1,6 @@
-run: async (parent: StepRow) => {
-  const supabase = createAdminClient();
-  const { data, error } = await supabase
+run: async (parent: StepRow, _args: unknown, context: GraphQLContext) => {
+  const client = getSystemClient(context);
+  const { data, error } = await client
     .from("run")
     .select("*")
     .eq("id", parent.run_id)

materializations (+6/-0)

Location: scheduler.ts:445system/type-resolvers.ts:172

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW
@@ -3,6 +3,12 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
+  // TODO(jabolo): Handle special case where the caller does
+  // not pass `orgIds` as `system`. In the new implementation,
+  // it will fail and return and empty connection as of now.
+  const _client = getSystemClient(context);
+
+  // eslint-disable-next-line @typescript-eslint/no-deprecated
   return queryWithPagination(args, context, {
     tableName: "materialization",
     whereSchema: MaterializationWhereSchema,

resolveTables (+4/-6)

Location: system.ts:732system/type-resolvers.ts:25

View Diff
===================================================================
--- system.ts	OLD
+++ system/type-resolvers.ts	NEW
@@ -1,23 +1,21 @@
 resolveTables: async (
   _: unknown,
+  // TODO(jabolo): Reconcile this input with a type from @/lib/graphql/generated/graphql
+  // eslint-disable-next-line oso-frontend/type-safety/no-inline-resolver-types
   input: {
     references: string[];
     metadata?: { orgName?: string; datasetName?: string };
   },
   context: GraphQLContext,
 ) => {
-  if (!context.systemCredentials) {
-    throw AuthenticationErrors.notAuthorized();
-  }
+  const client = getSystemClient(context);
 
   const { references, metadata } = validateInput(ResolveTablesSchema, input);
 
-  const supabase = createAdminClient();
-
   const tableResolvers = [
     new LegacyInferredTableResolver(),
     new MetadataInferredTableResolver(),
-    new DBTableResolver(supabase, [
+    new DBTableResolver(client, [
       (table) => {
         // If the catalog is iceberg return the table as is
         if (table.catalog === "iceberg") {
user/ (16 functions)
data-connection/ (1 functions)

dataConnections (+9/-4)

Location: data-connection.ts:87user/data-connection/queries.ts:14

View Diff
===================================================================
--- data-connection.ts	OLD
+++ user/data-connection/queries.ts	NEW
@@ -3,13 +3,18 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  return queryWithPagination(args, context, {
+  const { client, userId } = getAuthenticatedClient(context);
+  const orgIds = await getUserOrganizationIds(userId, client);
+
+  const options: ExplicitClientQueryOptions<"dynamic_connectors"> = {
+    client,
+    orgIds,
     tableName: "dynamic_connectors",
     whereSchema: DataConnectionWhereSchema,
-    requireAuth: true,
-    filterByUserOrgs: true,
     basePredicate: {
       is: [{ key: "deleted_at", value: null }],
     },
-  });
+  };
+
+  return queryWithPagination(args, context, options);
 };
data-model/ (1 functions)

dataModels (+9/-4)

Location: data-model.ts:41user/data-model/queries.ts:14

View Diff
===================================================================
--- data-model.ts	OLD
+++ user/data-model/queries.ts	NEW
@@ -3,13 +3,18 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  return queryWithPagination(args, context, {
+  const { client, userId } = getAuthenticatedClient(context);
+  const orgIds = await getUserOrganizationIds(userId, client);
+
+  const options: ExplicitClientQueryOptions<"model"> = {
+    client,
+    orgIds,
     tableName: "model",
     whereSchema: DataModelWhereSchema,
-    requireAuth: true,
-    filterByUserOrgs: true,
     basePredicate: {
       is: [{ key: "deleted_at", value: null }],
     },
-  });
+  };
+
+  return queryWithPagination(args, context, options);
 };
dataset/ (1 functions)

datasets (+9/-4)

Location: dataset.ts:43user/dataset/queries.ts:13

View Diff
===================================================================
--- dataset.ts	OLD
+++ user/dataset/queries.ts	NEW
@@ -3,13 +3,18 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  return queryWithPagination(args, context, {
+  const { client, userId } = getAuthenticatedClient(context);
+  const orgIds = await getUserOrganizationIds(userId, client);
+
+  const options: ExplicitClientQueryOptions<"datasets"> = {
+    client,
+    orgIds,
     tableName: "datasets",
     whereSchema: DatasetWhereSchema,
-    requireAuth: true,
-    filterByUserOrgs: true,
     basePredicate: {
       is: [{ key: "deleted_at", value: null }],
     },
-  });
+  };
+
+  return queryWithPagination(args, context, options);
 };
invitation/ (2 functions)

invitations (+5/-2)

Location: invitation.ts:33user/invitation/queries.ts:11

View Diff
===================================================================
--- invitation.ts	OLD
+++ user/invitation/queries.ts	NEW
@@ -3,10 +3,13 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
+  const { client, userId } = getAuthenticatedClient(context);
+  const orgIds = await getUserOrganizationIds(userId, client);
+
   return queryWithPagination(args, context, {
     tableName: "invitations",
     whereSchema: InvitationWhereSchema,
-    requireAuth: true,
-    filterByUserOrgs: true,
+    client,
+    orgIds,
   });
 };

acceptInvitation (+15/-12)

Location: invitation.ts:144user/invitation/mutations.ts:17

View Diff
===================================================================
--- invitation.ts	OLD
+++ user/invitation/mutations.ts	NEW
@@ -1,14 +1,12 @@
 acceptInvitation: async (
   _: unknown,
-  args: { input: { invitationId: string } },
+  args: MutationAcceptInvitationArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
   const input = validateInput(AcceptInvitationSchema, args.input);
+  const { client, userId } = getAuthenticatedClient(context);
 
-  const supabase = createAdminClient();
-
-  const { data: invitation, error: invError } = await supabase
+  const { data: invitation, error: invError } = await client
     .from("invitations")
     .select("*")
     .eq("id", input.invitationId)
@@ -30,15 +28,20 @@
     throw InvitationErrors.expired();
   }
 
-  const userEmail = authenticatedUser.email?.toLowerCase();
+  // Verify the authenticated user's email matches the invitation
+  if (context.user.role !== "user" || !context.user.email) {
+    throw InvitationErrors.wrongRecipient();
+  }
+
+  const userEmail = context.user.email.toLowerCase();
   if (userEmail !== invitation.email.toLowerCase()) {
     throw InvitationErrors.wrongRecipient();
   }
 
-  const { data: existingMembership } = await supabase
+  const { data: existingMembership } = await client
     .from("users_by_organization")
     .select("*")
-    .eq("user_id", authenticatedUser.userId)
+    .eq("user_id", userId)
     .eq("org_id", invitation.org_id)
     .is("deleted_at", null)
     .single();
@@ -47,11 +50,11 @@
     throw InvitationErrors.alreadyAccepted();
   }
 
-  const { error: acceptError } = await supabase
+  const { error: acceptError } = await client
     .from("invitations")
     .update({
       accepted_at: new Date().toISOString(),
-      accepted_by: authenticatedUser.userId,
+      accepted_by: userId,
     })
     .eq("id", input.invitationId);
 
@@ -61,10 +64,10 @@
     );
   }
 
-  const { data: member, error: memberError } = await supabase
+  const { data: member, error: memberError } = await client
     .from("users_by_organization")
     .insert({
-      user_id: authenticatedUser.userId,
+      user_id: userId,
       org_id: invitation.org_id,
       user_role: "admin",
     })
notebook/ (1 functions)

notebooks (+9/-4)

Location: notebook.ts:41user/notebook/queries.ts:13

View Diff
===================================================================
--- notebook.ts	OLD
+++ user/notebook/queries.ts	NEW
@@ -3,13 +3,18 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  return queryWithPagination(args, context, {
+  const { client, userId } = getAuthenticatedClient(context);
+  const orgIds = await getUserOrganizationIds(userId, client);
+
+  const options: ExplicitClientQueryOptions<"notebooks"> = {
+    client,
+    orgIds,
     tableName: "notebooks",
     whereSchema: NotebookWhereSchema,
-    requireAuth: true,
-    filterByUserOrgs: true,
     basePredicate: {
       is: [{ key: "deleted_at", value: null }],
     },
-  });
+  };
+
+  return queryWithPagination(args, context, options);
 };
organization/ (1 functions)

organizations (+10/-6)

Location: organization.ts:41user/organization/queries.ts:14

View Diff
===================================================================
--- organization.ts	OLD
+++ user/organization/queries.ts	NEW
@@ -3,15 +3,19 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  const authenticatedUser = requireAuthentication(context.user);
+  const { client, userId } = getAuthenticatedClient(context);
 
   const validatedWhere = args.where
     ? validateInput(OrganizationWhereSchema, args.where)
     : undefined;
 
-  return getUserOrganizationsConnection(
-    authenticatedUser.userId,
-    args,
-    validatedWhere ? parseWhereClause(validatedWhere) : undefined,
-  );
+  const predicate = validatedWhere
+    ? parseWhereClause(validatedWhere)
+    : undefined;
+
+  if (predicate) {
+    return getUserOrganizationsConnection(userId, args, predicate, client);
+  } else {
+    return getUserOrganizationsConnection(userId, args, undefined, client);
+  }
 };
static-model/ (1 functions)

staticModels (+9/-4)

Location: static-model.ts:40user/static-model/queries.ts:14

View Diff
===================================================================
--- static-model.ts	OLD
+++ user/static-model/queries.ts	NEW
@@ -3,13 +3,18 @@
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  return queryWithPagination(args, context, {
+  const { client, userId } = getAuthenticatedClient(context);
+  const orgIds = await getUserOrganizationIds(userId, client);
+
+  const options: ExplicitClientQueryOptions<"static_model"> = {
+    client,
+    orgIds,
     tableName: "static_model",
     whereSchema: StaticModelWhereSchema,
-    requireAuth: true,
-    filterByUserOrgs: true,
     basePredicate: {
       is: [{ key: "deleted_at", value: null }],
     },
-  });
+  };
+
+  return queryWithPagination(args, context, options);
 };
user/ (1 functions)

organizations (+5/-2)

Location: user.ts:17user/user/type-resolvers.ts:23

View Diff
===================================================================
--- user.ts	OLD
+++ user/user/type-resolvers.ts	NEW
@@ -1,8 +1,10 @@
 organizations: async (
   parent: UserProfilesRow,
   args: FilterableConnectionArgs,
-  _context: GraphQLContext,
+  context: GraphQLContext,
 ) => {
+  const { client } = getAuthenticatedClient(context);
+
   const validatedWhere = args.where
     ? validateInput(OrganizationWhereSchema, args.where)
     : undefined;
@@ -10,6 +12,7 @@
   return getUserOrganizationsConnection(
     parent.id,
     args,
-    validatedWhere ? parseWhereClause(validatedWhere) : undefined,
+    validatedWhere ? parseWhereClause(validatedWhere) : {},
+    client,
   );
 };
viewer/ (7 functions)

viewer (+3/-4)

Location: viewer.ts:24user/viewer/queries.ts:7

View Diff
===================================================================
--- viewer.ts	OLD
+++ user/viewer/queries.ts	NEW
@@ -1,11 +1,10 @@
 viewer: async (_: unknown, _args: unknown, context: GraphQLContext) => {
-  const authenticatedUser = requireAuthentication(context.user);
-  const supabase = createAdminClient();
+  const { client, userId } = getAuthenticatedClient(context);
 
-  const { data: profile, error } = await supabase
+  const { data: profile, error } = await client
     .from("user_profiles")
     .select("*")
-    .eq("id", authenticatedUser.userId)
+    .eq("id", userId)
     .single();
 
   if (error || !profile) {

fullName (+1/-1)

Location: viewer.ts:43user/viewer/type-resolvers.ts:31

View Diff
===================================================================
--- viewer.ts	OLD
+++ user/viewer/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-fullName: (parent: { full_name: string | null }) => parent.full_name;
+fullName: (parent: UserProfilesRow) => parent.full_name;

avatarUrl (+1/-1)

Location: viewer.ts:44user/viewer/type-resolvers.ts:32

View Diff
===================================================================
--- viewer.ts	OLD
+++ user/viewer/type-resolvers.ts	NEW
@@ -1,1 +1,1 @@
-avatarUrl: (parent: { avatar_url: string | null }) => parent.avatar_url;
+avatarUrl: (parent: UserProfilesRow) => parent.avatar_url;

organizations (+6/-3)

Location: viewer.ts:46user/viewer/type-resolvers.ts:34

View Diff
===================================================================
--- viewer.ts	OLD
+++ user/viewer/type-resolvers.ts	NEW
@@ -1,8 +1,10 @@
 organizations: async (
-  parent: { id: string },
+  parent: UserProfilesRow,
   args: FilterableConnectionArgs,
-  _context: GraphQLContext,
+  context: GraphQLContext,
 ) => {
+  const { client } = getAuthenticatedClient(context);
+
   const validatedWhere = args.where
     ? validateInput(OrganizationWhereSchema, args.where)
     : undefined;
@@ -10,6 +12,7 @@
   return getUserOrganizationsConnection(
     parent.id,
     args,
-    validatedWhere ? parseWhereClause(validatedWhere) : undefined,
+    validatedWhere ? parseWhereClause(validatedWhere) : {},
+    client,
   );
 };

notebooks (+9/-7)

Location: viewer.ts:62user/viewer/type-resolvers.ts:53

View Diff
===================================================================
--- viewer.ts	OLD
+++ user/viewer/type-resolvers.ts	NEW
@@ -1,18 +1,20 @@
 notebooks: async (
-  parent: { id: string },
+  parent: UserProfilesRow,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  const orgIds = await getUserOrganizationIds(parent.id);
+  const { client } = getAuthenticatedClient(context);
+  const orgIds = await getUserOrganizationIds(parent.id, client);
 
-  return queryWithPagination(args, context, {
+  const options: ExplicitClientQueryOptions<"notebooks"> = {
+    client,
+    orgIds,
     tableName: "notebooks",
     whereSchema: NotebookWhereSchema,
-    requireAuth: false,
-    filterByUserOrgs: false,
-    parentOrgIds: orgIds,
     basePredicate: {
       is: [{ key: "deleted_at", value: null }],
     },
-  });
+  };
+
+  return queryWithPagination(args, context, options);
 };

datasets (+9/-7)

Location: viewer.ts:81user/viewer/type-resolvers.ts:74

View Diff
===================================================================
--- viewer.ts	OLD
+++ user/viewer/type-resolvers.ts	NEW
@@ -1,18 +1,20 @@
 datasets: async (
-  parent: { id: string },
+  parent: UserProfilesRow,
   args: FilterableConnectionArgs,
   context: GraphQLContext,
 ) => {
-  const orgIds = await getUserOrganizationIds(parent.id);
+  const { client } = getAuthenticatedClient(context);
+  const orgIds = await getUserOrganizationIds(parent.id, client);
 
-  return queryWithPagination(args, context, {
+  const options: ExplicitClientQueryOptions<"datasets"> = {
+    client,
+    orgIds,
     tableName: "datasets",
     whereSchema: DatasetWhereSchema,
-    requireAuth: false,
-    filterByUserOrgs: false,
-    parentOrgIds: orgIds,
     basePredicate: {
       is: [{ key: "deleted_at", value: null }],
     },
-  });
+  };
+
+  return queryWithPagination(args, context, options);
 };

invitations (+6/-3)

Location: viewer.ts:100user/viewer/type-resolvers.ts:95

View Diff
===================================================================
--- viewer.ts	OLD
+++ user/viewer/type-resolvers.ts	NEW
@@ -1,8 +1,10 @@
 invitations: async (
-  parent: { id: string; email: string },
+  parent: UserProfilesRow,
   args: FilterableConnectionArgs,
-  _context: GraphQLContext,
+  context: GraphQLContext,
 ) => {
+  const { client } = getAuthenticatedClient(context);
+
   const validatedWhere = args.where
     ? validateInput(InvitationWhereSchema, args.where)
     : undefined;
@@ -10,6 +12,7 @@
   return getUserInvitationsConnection(
     parent.email,
     args,
-    validatedWhere ? parseWhereClause(validatedWhere) : undefined,
+    validatedWhere ? parseWhereClause(validatedWhere) : {},
+    client,
   );
 };

Migrated Functions (Unchanged - Same LOC)

resource/ (33 functions)
data-connection/ (12 functions)

orgId

Location: data-connection.ts:276resource/data-connection/type-resolvers.ts:21

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

createdAt

Location: data-connection.ts:280resource/data-connection/type-resolvers.ts:22

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

updatedAt

Location: data-connection.ts:281resource/data-connection/type-resolvers.ts:23

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

name

Location: data-connection.ts:282resource/data-connection/type-resolvers.ts:37

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

type

Location: data-connection.ts:283resource/data-connection/type-resolvers.ts:38

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

orgId

Location: data-connection.ts:287resource/data-connection/type-resolvers.ts:43

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

datasetId

Location: data-connection.ts:288resource/data-connection/type-resolvers.ts:44

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

schema

Location: data-connection.ts:289resource/data-connection/type-resolvers.ts:47

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

dataConnectionId

Location: data-connection.ts:290resource/data-connection/type-resolvers.ts:45

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

createdAt

Location: data-connection.ts:292resource/data-connection/type-resolvers.ts:48

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

updatedAt

Location: data-connection.ts:293resource/data-connection/type-resolvers.ts:49

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW

materializations

Location: data-connection.ts:294resource/data-connection/type-resolvers.ts:50

View Diff
===================================================================
--- data-connection.ts	OLD
+++ resource/data-connection/type-resolvers.ts	NEW
data-ingestion/ (7 functions)

id

Location: data-ingestion.ts:97resource/data-ingestion/type-resolvers.ts:20

View Diff
===================================================================
--- data-ingestion.ts	OLD
+++ resource/data-ingestion/type-resolvers.ts	NEW

datasetId

Location: data-ingestion.ts:115resource/data-ingestion/type-resolvers.ts:46

View Diff
===================================================================
--- data-ingestion.ts	OLD
+++ resource/data-ingestion/type-resolvers.ts	NEW

factoryType

Location: data-ingestion.ts:116resource/data-ingestion/type-resolvers.ts:47

View Diff
===================================================================
--- data-ingestion.ts	OLD
+++ resource/data-ingestion/type-resolvers.ts	NEW

config

Location: data-ingestion.ts:117resource/data-ingestion/type-resolvers.ts:48

View Diff
===================================================================
--- data-ingestion.ts	OLD
+++ resource/data-ingestion/type-resolvers.ts	NEW

createdAt

Location: data-ingestion.ts:118resource/data-ingestion/type-resolvers.ts:49

View Diff
===================================================================
--- data-ingestion.ts	OLD
+++ resource/data-ingestion/type-resolvers.ts	NEW

updatedAt

Location: data-ingestion.ts:119resource/data-ingestion/type-resolvers.ts:50

View Diff
===================================================================
--- data-ingestion.ts	OLD
+++ resource/data-ingestion/type-resolvers.ts	NEW

materializations

Location: data-ingestion.ts:126resource/data-ingestion/type-resolvers.ts:59

View Diff
===================================================================
--- data-ingestion.ts	OLD
+++ resource/data-ingestion/type-resolvers.ts	NEW
data-model/ (2 functions)

modelContext

Location: data-model.ts:449resource/data-model/type-resolvers.ts:187

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW

materializations

Location: data-model.ts:452resource/data-model/type-resolvers.ts:190

View Diff
===================================================================
--- data-model.ts	OLD
+++ resource/data-model/type-resolvers.ts	NEW
model-context/ (7 functions)

orgId

Location: model-context.ts:127resource/model-context/type-resolvers.ts:13

View Diff
===================================================================
--- model-context.ts	OLD
+++ resource/model-context/type-resolvers.ts	NEW

datasetId

Location: model-context.ts:128resource/model-context/type-resolvers.ts:14

View Diff
===================================================================
--- model-context.ts	OLD
+++ resource/model-context/type-resolvers.ts	NEW

tableId

Location: model-context.ts:129resource/model-context/type-resolvers.ts:15

View Diff
===================================================================
--- model-context.ts	OLD
+++ resource/model-context/type-resolvers.ts	NEW

context

Location: model-context.ts:130resource/model-context/type-resolvers.ts:16

View Diff
===================================================================
--- model-context.ts	OLD
+++ resource/model-context/type-resolvers.ts	NEW

columnContext

Location: model-context.ts:131resource/model-context/type-resolvers.ts:17

View Diff
===================================================================
--- model-context.ts	OLD
+++ resource/model-context/type-resolvers.ts	NEW

createdAt

Location: model-context.ts:132resource/model-context/type-resolvers.ts:18

View Diff
===================================================================
--- model-context.ts	OLD
+++ resource/model-context/type-resolvers.ts	NEW

updatedAt

Location: model-context.ts:133resource/model-context/type-resolvers.ts:19

View Diff
===================================================================
--- model-context.ts	OLD
+++ resource/model-context/type-resolvers.ts	NEW
static-model/ (5 functions)

orgId

Location: static-model.ts:215resource/static-model/type-resolvers.ts:25

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/type-resolvers.ts	NEW

createdAt

Location: static-model.ts:229resource/static-model/type-resolvers.ts:60

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/type-resolvers.ts	NEW

updatedAt

Location: static-model.ts:232resource/static-model/type-resolvers.ts:63

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/type-resolvers.ts	NEW

modelContext

Location: static-model.ts:238resource/static-model/type-resolvers.ts:78

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/type-resolvers.ts	NEW

materializations

Location: static-model.ts:241resource/static-model/type-resolvers.ts:81

View Diff
===================================================================
--- static-model.ts	OLD
+++ resource/static-model/type-resolvers.ts	NEW
system/ (21 functions)
run-type-resolvers.ts/ (10 functions)

datasetId

Location: scheduler.ts:271system/run-type-resolvers.ts:43

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW

orgId

Location: scheduler.ts:292system/run-type-resolvers.ts:68

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW

triggerType

Location: scheduler.ts:310system/run-type-resolvers.ts:90

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW

runType

Location: scheduler.ts:314system/run-type-resolvers.ts:94

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW

queuedAt

Location: scheduler.ts:316system/run-type-resolvers.ts:96

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW

status

Location: scheduler.ts:317system/run-type-resolvers.ts:97

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW

startedAt

Location: scheduler.ts:318system/run-type-resolvers.ts:98

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW

finishedAt

Location: scheduler.ts:319system/run-type-resolvers.ts:99

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW

logsUrl

Location: scheduler.ts:320system/run-type-resolvers.ts:100

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW

metadata

Location: scheduler.ts:362system/run-type-resolvers.ts:153

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/run-type-resolvers.ts	NEW
type-resolvers.ts/ (11 functions)

runId

Location: scheduler.ts:365system/type-resolvers.ts:88

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW

datasetId

Location: scheduler.ts:384system/type-resolvers.ts:110

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW

createdAt

Location: scheduler.ts:385system/type-resolvers.ts:111

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW

schema

Location: scheduler.ts:386system/type-resolvers.ts:112

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW

runId

Location: scheduler.ts:389system/type-resolvers.ts:116

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW

name

Location: scheduler.ts:407system/type-resolvers.ts:134

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW

displayName

Location: scheduler.ts:408system/type-resolvers.ts:135

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW

logsUrl

Location: scheduler.ts:409system/type-resolvers.ts:136

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW

startedAt

Location: scheduler.ts:429system/type-resolvers.ts:156

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW

finishedAt

Location: scheduler.ts:430system/type-resolvers.ts:157

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW

status

Location: scheduler.ts:431system/type-resolvers.ts:158

View Diff
===================================================================
--- scheduler.ts	OLD
+++ system/type-resolvers.ts	NEW
user/ (3 functions)
user/ (3 functions)

fullName

Location: user.ts:14user/user/type-resolvers.ts:20

View Diff
===================================================================
--- user.ts	OLD
+++ user/user/type-resolvers.ts	NEW

avatarUrl

Location: user.ts:15user/user/type-resolvers.ts:21

View Diff
===================================================================
--- user.ts	OLD
+++ user/user/type-resolvers.ts	NEW

email

Location: user.ts:16user/user/type-resolvers.ts:22

View Diff
===================================================================
--- user.ts	OLD
+++ user/user/type-resolvers.ts	NEW

@vercel
Copy link

vercel bot commented Feb 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
kariba-network Ready Ready Preview, Comment Feb 5, 2026 2:42am
oso-www Ready Ready Preview, Comment Feb 5, 2026 2:42am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant