diff --git a/backend/src/@types/fastify.d.ts b/backend/src/@types/fastify.d.ts
index 02159fa9cb..f3298625e6 100644
--- a/backend/src/@types/fastify.d.ts
+++ b/backend/src/@types/fastify.d.ts
@@ -80,6 +80,7 @@ import { TSecretFolderServiceFactory } from "@app/services/secret-folder/secret-
 import { TSecretImportServiceFactory } from "@app/services/secret-import/secret-import-service";
 import { TSecretReplicationServiceFactory } from "@app/services/secret-replication/secret-replication-service";
 import { TSecretSharingServiceFactory } from "@app/services/secret-sharing/secret-sharing-service";
+import { TSecretSyncServiceFactory } from "@app/services/secret-sync/secret-sync-service";
 import { TSecretTagServiceFactory } from "@app/services/secret-tag/secret-tag-service";
 import { TServiceTokenServiceFactory } from "@app/services/service-token/service-token-service";
 import { TSlackServiceFactory } from "@app/services/slack/slack-service";
@@ -210,6 +211,7 @@ declare module "fastify" {
       projectTemplate: TProjectTemplateServiceFactory;
       totp: TTotpServiceFactory;
       appConnection: TAppConnectionServiceFactory;
+      secretSync: TSecretSyncServiceFactory;
     };
     // this is exclusive use for middlewares in which we need to inject data
     // everywhere else access using service layer
diff --git a/backend/src/@types/knex.d.ts b/backend/src/@types/knex.d.ts
index aaa2014b8d..2dad77392b 100644
--- a/backend/src/@types/knex.d.ts
+++ b/backend/src/@types/knex.d.ts
@@ -372,6 +372,7 @@ import {
   TExternalGroupOrgRoleMappingsInsert,
   TExternalGroupOrgRoleMappingsUpdate
 } from "@app/db/schemas/external-group-org-role-mappings";
+import { TSecretSyncs, TSecretSyncsInsert, TSecretSyncsUpdate } from "@app/db/schemas/secret-syncs";
 import {
   TSecretV2TagJunction,
   TSecretV2TagJunctionInsert,
@@ -900,5 +901,6 @@ declare module "knex/types/tables" {
       TAppConnectionsInsert,
       TAppConnectionsUpdate
     >;
+    [TableName.SecretSync]: KnexOriginal.CompositeTableType<TSecretSyncs, TSecretSyncsInsert, TSecretSyncsUpdate>;
   }
 }
diff --git a/backend/src/db/migrations/20250122055102_secret-sync.ts b/backend/src/db/migrations/20250122055102_secret-sync.ts
new file mode 100644
index 0000000000..5f37950e34
--- /dev/null
+++ b/backend/src/db/migrations/20250122055102_secret-sync.ts
@@ -0,0 +1,50 @@
+import { Knex } from "knex";
+
+import { TableName } from "@app/db/schemas";
+import { createOnUpdateTrigger, dropOnUpdateTrigger } from "@app/db/utils";
+
+export async function up(knex: Knex): Promise<void> {
+  if (!(await knex.schema.hasTable(TableName.SecretSync))) {
+    await knex.schema.createTable(TableName.SecretSync, (t) => {
+      t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
+      t.string("name", 32).notNullable();
+      t.string("description");
+      t.string("destination").notNullable();
+      t.boolean("isAutoSyncEnabled").notNullable().defaultTo(true);
+      t.integer("version").defaultTo(1).notNullable();
+      t.jsonb("destinationConfig").notNullable();
+      t.jsonb("syncOptions").notNullable();
+      // we're including projectId in addition to folder ID because we allow folderId to be null (if the folder
+      // is deleted), to preserve sync configuration
+      t.string("projectId").notNullable();
+      t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
+      t.uuid("folderId");
+      t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("SET NULL");
+      t.uuid("connectionId").notNullable();
+      t.foreign("connectionId").references("id").inTable(TableName.AppConnection);
+      t.timestamps(true, true, true);
+      // sync secrets to destination
+      t.string("syncStatus");
+      t.string("lastSyncJobId");
+      t.string("lastSyncMessage");
+      t.datetime("lastSyncedAt");
+      // import secrets from destination
+      t.string("importStatus");
+      t.string("lastImportJobId");
+      t.string("lastImportMessage");
+      t.datetime("lastImportedAt");
+      // remove secrets from destination
+      t.string("removeStatus");
+      t.string("lastRemoveJobId");
+      t.string("lastRemoveMessage");
+      t.datetime("lastRemovedAt");
+    });
+
+    await createOnUpdateTrigger(knex, TableName.SecretSync);
+  }
+}
+
+export async function down(knex: Knex): Promise<void> {
+  await knex.schema.dropTableIfExists(TableName.SecretSync);
+  await dropOnUpdateTrigger(knex, TableName.SecretSync);
+}
diff --git a/backend/src/db/schemas/models.ts b/backend/src/db/schemas/models.ts
index c991b913d2..3ead855305 100644
--- a/backend/src/db/schemas/models.ts
+++ b/backend/src/db/schemas/models.ts
@@ -131,7 +131,8 @@ export enum TableName {
   WorkflowIntegrations = "workflow_integrations",
   SlackIntegrations = "slack_integrations",
   ProjectSlackConfigs = "project_slack_configs",
-  AppConnection = "app_connections"
+  AppConnection = "app_connections",
+  SecretSync = "secret_syncs"
 }
 
 export type TImmutableDBKeys = "id" | "createdAt" | "updatedAt";
diff --git a/backend/src/db/schemas/secret-syncs.ts b/backend/src/db/schemas/secret-syncs.ts
new file mode 100644
index 0000000000..0e0728e874
--- /dev/null
+++ b/backend/src/db/schemas/secret-syncs.ts
@@ -0,0 +1,40 @@
+// Code generated by automation script, DO NOT EDIT.
+// Automated by pulling database and generating zod schema
+// To update. Just run npm run generate:schema
+// Written by akhilmhdh.
+
+import { z } from "zod";
+
+import { TImmutableDBKeys } from "./models";
+
+export const SecretSyncsSchema = z.object({
+  id: z.string().uuid(),
+  name: z.string(),
+  description: z.string().nullable().optional(),
+  destination: z.string(),
+  isAutoSyncEnabled: z.boolean().default(true),
+  version: z.number().default(1),
+  destinationConfig: z.unknown(),
+  syncOptions: z.unknown(),
+  projectId: z.string(),
+  folderId: z.string().uuid().nullable().optional(),
+  connectionId: z.string().uuid(),
+  createdAt: z.date(),
+  updatedAt: z.date(),
+  syncStatus: z.string().nullable().optional(),
+  lastSyncJobId: z.string().nullable().optional(),
+  lastSyncMessage: z.string().nullable().optional(),
+  lastSyncedAt: z.date().nullable().optional(),
+  importStatus: z.string().nullable().optional(),
+  lastImportJobId: z.string().nullable().optional(),
+  lastImportMessage: z.string().nullable().optional(),
+  lastImportedAt: z.date().nullable().optional(),
+  removeStatus: z.string().nullable().optional(),
+  lastRemoveJobId: z.string().nullable().optional(),
+  lastRemoveMessage: z.string().nullable().optional(),
+  lastRemovedAt: z.date().nullable().optional()
+});
+
+export type TSecretSyncs = z.infer<typeof SecretSyncsSchema>;
+export type TSecretSyncsInsert = Omit<z.input<typeof SecretSyncsSchema>, TImmutableDBKeys>;
+export type TSecretSyncsUpdate = Partial<Omit<z.input<typeof SecretSyncsSchema>, TImmutableDBKeys>>;
diff --git a/backend/src/ee/routes/v1/org-role-router.ts b/backend/src/ee/routes/v1/org-role-router.ts
index 3a0ad47dac..c8ee03a99b 100644
--- a/backend/src/ee/routes/v1/org-role-router.ts
+++ b/backend/src/ee/routes/v1/org-role-router.ts
@@ -24,6 +24,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
         ),
         name: z.string().trim(),
         description: z.string().trim().nullish(),
+        // TODO(scott): once UI refactored permissions: OrgPermissionSchema.array()
         permissions: z.any().array()
       }),
       response: {
@@ -96,6 +97,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
           .optional(),
         name: z.string().trim().optional(),
         description: z.string().trim().nullish(),
+        // TODO(scott): once UI refactored permissions: OrgPermissionSchema.array().optional()
         permissions: z.any().array().optional()
       }),
       response: {
diff --git a/backend/src/ee/services/audit-log/audit-log-service.ts b/backend/src/ee/services/audit-log/audit-log-service.ts
index e51c08fbe9..ff7dede5fc 100644
--- a/backend/src/ee/services/audit-log/audit-log-service.ts
+++ b/backend/src/ee/services/audit-log/audit-log-service.ts
@@ -81,7 +81,8 @@ export const auditLogServiceFactory = ({
     }
     // add all cases in which project id or org id cannot be added
     if (data.event.type !== EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH) {
-      if (!data.projectId && !data.orgId) throw new BadRequestError({ message: "Must either project id or org id" });
+      if (!data.projectId && !data.orgId)
+        throw new BadRequestError({ message: "Must specify either project id or org id" });
     }
 
     return auditLogQueue.pushToLog(data);
diff --git a/backend/src/ee/services/audit-log/audit-log-types.ts b/backend/src/ee/services/audit-log/audit-log-types.ts
index 2a5657cf0c..9c19cd3ccb 100644
--- a/backend/src/ee/services/audit-log/audit-log-types.ts
+++ b/backend/src/ee/services/audit-log/audit-log-types.ts
@@ -13,6 +13,13 @@ import { CertKeyAlgorithm } from "@app/services/certificate/certificate-types";
 import { CaStatus } from "@app/services/certificate-authority/certificate-authority-types";
 import { TIdentityTrustedIp } from "@app/services/identity/identity-types";
 import { PkiItemType } from "@app/services/pki-collection/pki-collection-types";
+import { SecretSync, SecretSyncImportBehavior } from "@app/services/secret-sync/secret-sync-enums";
+import {
+  TCreateSecretSyncDTO,
+  TDeleteSecretSyncDTO,
+  TSecretSyncRaw,
+  TUpdateSecretSyncDTO
+} from "@app/services/secret-sync/secret-sync-types";
 
 export type TListProjectAuditLogDTO = {
   filter: {
@@ -226,13 +233,22 @@ export enum EventType {
   DELETE_PROJECT_TEMPLATE = "delete-project-template",
   APPLY_PROJECT_TEMPLATE = "apply-project-template",
   GET_APP_CONNECTIONS = "get-app-connections",
+  GET_AVAILABLE_APP_CONNECTIONS_DETAILS = "get-available-app-connections-details",
   GET_APP_CONNECTION = "get-app-connection",
   CREATE_APP_CONNECTION = "create-app-connection",
   UPDATE_APP_CONNECTION = "update-app-connection",
   DELETE_APP_CONNECTION = "delete-app-connection",
   CREATE_SHARED_SECRET = "create-shared-secret",
   DELETE_SHARED_SECRET = "delete-shared-secret",
-  READ_SHARED_SECRET = "read-shared-secret"
+  READ_SHARED_SECRET = "read-shared-secret",
+  GET_SECRET_SYNCS = "get-secret-syncs",
+  GET_SECRET_SYNC = "get-secret-sync",
+  CREATE_SECRET_SYNC = "create-secret-sync",
+  UPDATE_SECRET_SYNC = "update-secret-sync",
+  DELETE_SECRET_SYNC = "delete-secret-sync",
+  SECRET_SYNC_SYNC_SECRETS = "secret-sync-sync-secrets",
+  SECRET_SYNC_IMPORT_SECRETS = "secret-sync-import-secrets",
+  SECRET_SYNC_REMOVE_SECRETS = "secret-sync-remove-secrets"
 }
 
 interface UserActorMetadata {
@@ -1893,6 +1909,15 @@ interface GetAppConnectionsEvent {
   };
 }
 
+interface GetAvailableAppConnectionsDetailsEvent {
+  type: EventType.GET_AVAILABLE_APP_CONNECTIONS_DETAILS;
+  metadata: {
+    app?: AppConnection;
+    count: number;
+    connectionIds: string[];
+  };
+}
+
 interface GetAppConnectionEvent {
   type: EventType.GET_APP_CONNECTION;
   metadata: {
@@ -1946,6 +1971,78 @@ interface ReadSharedSecretEvent {
   };
 }
 
+interface GetSecretSyncsEvent {
+  type: EventType.GET_SECRET_SYNCS;
+  metadata: {
+    destination?: SecretSync;
+    count: number;
+    syncIds: string[];
+  };
+}
+
+interface GetSecretSyncEvent {
+  type: EventType.GET_SECRET_SYNC;
+  metadata: {
+    destination: SecretSync;
+    syncId: string;
+  };
+}
+
+interface CreateSecretSyncEvent {
+  type: EventType.CREATE_SECRET_SYNC;
+  metadata: Omit<TCreateSecretSyncDTO, "projectId"> & { syncId: string };
+}
+
+interface UpdateSecretSyncEvent {
+  type: EventType.UPDATE_SECRET_SYNC;
+  metadata: TUpdateSecretSyncDTO;
+}
+
+interface DeleteSecretSyncEvent {
+  type: EventType.DELETE_SECRET_SYNC;
+  metadata: TDeleteSecretSyncDTO;
+}
+
+interface SecretSyncSyncSecretsEvent {
+  type: EventType.SECRET_SYNC_SYNC_SECRETS;
+  metadata: Pick<
+    TSecretSyncRaw,
+    "syncOptions" | "destinationConfig" | "destination" | "syncStatus" | "connectionId" | "folderId"
+  > & {
+    syncId: string;
+    syncMessage: string | null;
+    jobId: string;
+    jobRanAt: Date;
+  };
+}
+
+interface SecretSyncImportSecretsEvent {
+  type: EventType.SECRET_SYNC_IMPORT_SECRETS;
+  metadata: Pick<
+    TSecretSyncRaw,
+    "syncOptions" | "destinationConfig" | "destination" | "importStatus" | "connectionId" | "folderId"
+  > & {
+    syncId: string;
+    importMessage: string | null;
+    jobId: string;
+    jobRanAt: Date;
+    importBehavior: SecretSyncImportBehavior;
+  };
+}
+
+interface SecretSyncRemoveSecretsEvent {
+  type: EventType.SECRET_SYNC_REMOVE_SECRETS;
+  metadata: Pick<
+    TSecretSyncRaw,
+    "syncOptions" | "destinationConfig" | "destination" | "removeStatus" | "connectionId" | "folderId"
+  > & {
+    syncId: string;
+    removeMessage: string | null;
+    jobId: string;
+    jobRanAt: Date;
+  };
+}
+
 export type Event =
   | GetSecretsEvent
   | GetSecretEvent
@@ -2119,10 +2216,19 @@ export type Event =
   | DeleteProjectTemplateEvent
   | ApplyProjectTemplateEvent
   | GetAppConnectionsEvent
+  | GetAvailableAppConnectionsDetailsEvent
   | GetAppConnectionEvent
   | CreateAppConnectionEvent
   | UpdateAppConnectionEvent
   | DeleteAppConnectionEvent
   | CreateSharedSecretEvent
   | DeleteSharedSecretEvent
-  | ReadSharedSecretEvent;
+  | ReadSharedSecretEvent
+  | GetSecretSyncsEvent
+  | GetSecretSyncEvent
+  | CreateSecretSyncEvent
+  | UpdateSecretSyncEvent
+  | DeleteSecretSyncEvent
+  | SecretSyncSyncSecretsEvent
+  | SecretSyncImportSecretsEvent
+  | SecretSyncRemoveSecretsEvent;
diff --git a/backend/src/ee/services/license/license-fns.ts b/backend/src/ee/services/license/license-fns.ts
index 014fcccfd4..c54daa3a64 100644
--- a/backend/src/ee/services/license/license-fns.ts
+++ b/backend/src/ee/services/license/license-fns.ts
@@ -50,8 +50,7 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
   },
   pkiEst: false,
   enforceMfa: false,
-  projectTemplates: false,
-  appConnections: false
+  projectTemplates: false
 });
 
 export const setupLicenseRequestWithStore = (baseURL: string, refreshUrl: string, licenseKey: string) => {
diff --git a/backend/src/ee/services/license/license-types.ts b/backend/src/ee/services/license/license-types.ts
index 678e15fd46..0242377b04 100644
--- a/backend/src/ee/services/license/license-types.ts
+++ b/backend/src/ee/services/license/license-types.ts
@@ -68,7 +68,6 @@ export type TFeatureSet = {
   pkiEst: boolean;
   enforceMfa: boolean;
   projectTemplates: false;
-  appConnections: false; // TODO: remove once live
 };
 
 export type TOrgPlansTableDTO = {
diff --git a/backend/src/ee/services/permission/org-permission.ts b/backend/src/ee/services/permission/org-permission.ts
index 487d2155c8..c72008057f 100644
--- a/backend/src/ee/services/permission/org-permission.ts
+++ b/backend/src/ee/services/permission/org-permission.ts
@@ -1,4 +1,12 @@
-import { AbilityBuilder, createMongoAbility, MongoAbility } from "@casl/ability";
+import { AbilityBuilder, createMongoAbility, ForcedSubject, MongoAbility } from "@casl/ability";
+import { z } from "zod";
+
+import {
+  CASL_ACTION_SCHEMA_ENUM,
+  CASL_ACTION_SCHEMA_NATIVE_ENUM
+} from "@app/ee/services/permission/permission-schemas";
+import { PermissionConditionSchema } from "@app/ee/services/permission/permission-types";
+import { PermissionConditionOperators } from "@app/lib/casl";
 
 export enum OrgPermissionActions {
   Read = "read",
@@ -7,6 +15,14 @@ export enum OrgPermissionActions {
   Delete = "delete"
 }
 
+export enum OrgPermissionAppConnectionActions {
+  Read = "read",
+  Create = "create",
+  Edit = "edit",
+  Delete = "delete",
+  Connect = "connect"
+}
+
 export enum OrgPermissionAdminConsoleAction {
   AccessAllProjects = "access-all-projects"
 }
@@ -31,6 +47,10 @@ export enum OrgPermissionSubjects {
   AppConnections = "app-connections"
 }
 
+export type AppConnectionSubjectFields = {
+  connectionId: string;
+};
+
 export type OrgPermissionSet =
   | [OrgPermissionActions.Create, OrgPermissionSubjects.Workspace]
   | [OrgPermissionActions, OrgPermissionSubjects.Role]
@@ -47,9 +67,109 @@ export type OrgPermissionSet =
   | [OrgPermissionActions, OrgPermissionSubjects.Kms]
   | [OrgPermissionActions, OrgPermissionSubjects.AuditLogs]
   | [OrgPermissionActions, OrgPermissionSubjects.ProjectTemplates]
-  | [OrgPermissionActions, OrgPermissionSubjects.AppConnections]
+  | [
+      OrgPermissionAppConnectionActions,
+      (
+        | OrgPermissionSubjects.AppConnections
+        | (ForcedSubject<OrgPermissionSubjects.AppConnections> & AppConnectionSubjectFields)
+      )
+    ]
   | [OrgPermissionAdminConsoleAction, OrgPermissionSubjects.AdminConsole];
 
+const AppConnectionConditionSchema = z
+  .object({
+    connectionId: z.union([
+      z.string(),
+      z
+        .object({
+          [PermissionConditionOperators.$EQ]: PermissionConditionSchema[PermissionConditionOperators.$EQ],
+          [PermissionConditionOperators.$NEQ]: PermissionConditionSchema[PermissionConditionOperators.$NEQ],
+          [PermissionConditionOperators.$IN]: PermissionConditionSchema[PermissionConditionOperators.$IN]
+        })
+        .partial()
+    ])
+  })
+  .partial();
+
+export const OrgPermissionSchema = z.discriminatedUnion("subject", [
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Workspace).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_ENUM([OrgPermissionActions.Create]).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Role).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Member).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Settings).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.IncidentAccount).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Sso).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Scim).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Ldap).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Groups).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.SecretScanning).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Billing).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Identity).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.Kms).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.AuditLogs).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.ProjectTemplates).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.AppConnections).describe("The entity this permission pertains to."),
+    inverted: z.boolean().optional().describe("Whether rule allows or forbids."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionAppConnectionActions).describe(
+      "Describe what action an entity can take."
+    ),
+    conditions: AppConnectionConditionSchema.describe(
+      "When specified, only matching conditions will be allowed to access given resource."
+    ).optional()
+  }),
+  z.object({
+    subject: z.literal(OrgPermissionSubjects.AdminConsole).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionAdminConsoleAction).describe(
+      "Describe what action an entity can take."
+    )
+  })
+]);
+
 const buildAdminPermission = () => {
   const { can, rules } = new AbilityBuilder<MongoAbility<OrgPermissionSet>>(createMongoAbility);
   // ws permissions
@@ -125,10 +245,11 @@ const buildAdminPermission = () => {
   can(OrgPermissionActions.Edit, OrgPermissionSubjects.ProjectTemplates);
   can(OrgPermissionActions.Delete, OrgPermissionSubjects.ProjectTemplates);
 
-  can(OrgPermissionActions.Read, OrgPermissionSubjects.AppConnections);
-  can(OrgPermissionActions.Create, OrgPermissionSubjects.AppConnections);
-  can(OrgPermissionActions.Edit, OrgPermissionSubjects.AppConnections);
-  can(OrgPermissionActions.Delete, OrgPermissionSubjects.AppConnections);
+  can(OrgPermissionAppConnectionActions.Read, OrgPermissionSubjects.AppConnections);
+  can(OrgPermissionAppConnectionActions.Create, OrgPermissionSubjects.AppConnections);
+  can(OrgPermissionAppConnectionActions.Edit, OrgPermissionSubjects.AppConnections);
+  can(OrgPermissionAppConnectionActions.Delete, OrgPermissionSubjects.AppConnections);
+  can(OrgPermissionAppConnectionActions.Connect, OrgPermissionSubjects.AppConnections);
 
   can(OrgPermissionAdminConsoleAction.AccessAllProjects, OrgPermissionSubjects.AdminConsole);
 
@@ -160,7 +281,7 @@ const buildMemberPermission = () => {
 
   can(OrgPermissionActions.Read, OrgPermissionSubjects.AuditLogs);
 
-  can(OrgPermissionActions.Read, OrgPermissionSubjects.AppConnections);
+  can(OrgPermissionAppConnectionActions.Connect, OrgPermissionSubjects.AppConnections);
 
   return rules;
 };
diff --git a/backend/src/ee/services/permission/permission-schemas.ts b/backend/src/ee/services/permission/permission-schemas.ts
new file mode 100644
index 0000000000..fb462e4aac
--- /dev/null
+++ b/backend/src/ee/services/permission/permission-schemas.ts
@@ -0,0 +1,9 @@
+import { z } from "zod";
+
+export const CASL_ACTION_SCHEMA_NATIVE_ENUM = <ACTION extends z.EnumLike>(actions: ACTION) =>
+  z
+    .union([z.nativeEnum(actions), z.nativeEnum(actions).array().min(1)])
+    .transform((el) => (typeof el === "string" ? [el] : el));
+
+export const CASL_ACTION_SCHEMA_ENUM = <ACTION extends z.EnumValues>(actions: ACTION) =>
+  z.union([z.enum(actions), z.enum(actions).array().min(1)]).transform((el) => (typeof el === "string" ? [el] : el));
diff --git a/backend/src/ee/services/permission/project-permission.ts b/backend/src/ee/services/permission/project-permission.ts
index 47142054e6..3dc7daddca 100644
--- a/backend/src/ee/services/permission/project-permission.ts
+++ b/backend/src/ee/services/permission/project-permission.ts
@@ -1,6 +1,10 @@
 import { AbilityBuilder, createMongoAbility, ForcedSubject, MongoAbility } from "@casl/ability";
 import { z } from "zod";
 
+import {
+  CASL_ACTION_SCHEMA_ENUM,
+  CASL_ACTION_SCHEMA_NATIVE_ENUM
+} from "@app/ee/services/permission/permission-schemas";
 import { conditionsMatcher, PermissionConditionOperators } from "@app/lib/casl";
 import { UnpackedPermissionSchema } from "@app/server/routes/santizedSchemas/permission";
 
@@ -30,6 +34,16 @@ export enum ProjectPermissionDynamicSecretActions {
   Lease = "lease"
 }
 
+export enum ProjectPermissionSecretSyncActions {
+  Read = "read",
+  Create = "create",
+  Edit = "edit",
+  Delete = "delete",
+  SyncSecrets = "sync-secrets",
+  ImportSecrets = "import-secrets",
+  RemoveSecrets = "remove-secrets"
+}
+
 export enum ProjectPermissionSub {
   Role = "role",
   Member = "member",
@@ -60,7 +74,8 @@ export enum ProjectPermissionSub {
   PkiAlerts = "pki-alerts",
   PkiCollections = "pki-collections",
   Kms = "kms",
-  Cmek = "cmek"
+  Cmek = "cmek",
+  SecretSyncs = "secret-syncs"
 }
 
 export type SecretSubjectFields = {
@@ -140,6 +155,7 @@ export type ProjectPermissionSet =
   | [ProjectPermissionActions, ProjectPermissionSub.SshCertificateTemplates]
   | [ProjectPermissionActions, ProjectPermissionSub.PkiAlerts]
   | [ProjectPermissionActions, ProjectPermissionSub.PkiCollections]
+  | [ProjectPermissionSecretSyncActions, ProjectPermissionSub.SecretSyncs]
   | [ProjectPermissionCmekActions, ProjectPermissionSub.Cmek]
   | [ProjectPermissionActions.Delete, ProjectPermissionSub.Project]
   | [ProjectPermissionActions.Edit, ProjectPermissionSub.Project]
@@ -147,14 +163,6 @@ export type ProjectPermissionSet =
   | [ProjectPermissionActions.Create, ProjectPermissionSub.SecretRollback]
   | [ProjectPermissionActions.Edit, ProjectPermissionSub.Kms];
 
-const CASL_ACTION_SCHEMA_NATIVE_ENUM = <ACTION extends z.EnumLike>(actions: ACTION) =>
-  z
-    .union([z.nativeEnum(actions), z.nativeEnum(actions).array().min(1)])
-    .transform((el) => (typeof el === "string" ? [el] : el));
-
-const CASL_ACTION_SCHEMA_ENUM = <ACTION extends z.EnumValues>(actions: ACTION) =>
-  z.union([z.enum(actions), z.enum(actions).array().min(1)]).transform((el) => (typeof el === "string" ? [el] : el));
-
 // akhilmhdh: don't modify this for v2
 // if you want to update create a new schema
 const SecretConditionV1Schema = z
@@ -392,10 +400,15 @@ const GeneralPermissionSchema = [
   }),
   z.object({
     subject: z.literal(ProjectPermissionSub.Cmek).describe("The entity this permission pertains to."),
-    inverted: z.boolean().optional().describe("Whether rule allows or forbids."),
     action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionCmekActions).describe(
       "Describe what action an entity can take."
     )
+  }),
+  z.object({
+    subject: z.literal(ProjectPermissionSub.SecretSyncs).describe("The entity this permission pertains to."),
+    action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionSecretSyncActions).describe(
+      "Describe what action an entity can take."
+    )
   })
 ];
 
@@ -549,6 +562,18 @@ const buildAdminPermissionRules = () => {
     ],
     ProjectPermissionSub.Cmek
   );
+  can(
+    [
+      ProjectPermissionSecretSyncActions.Create,
+      ProjectPermissionSecretSyncActions.Edit,
+      ProjectPermissionSecretSyncActions.Delete,
+      ProjectPermissionSecretSyncActions.Read,
+      ProjectPermissionSecretSyncActions.SyncSecrets,
+      ProjectPermissionSecretSyncActions.ImportSecrets,
+      ProjectPermissionSecretSyncActions.RemoveSecrets
+    ],
+    ProjectPermissionSub.SecretSyncs
+  );
   return rules;
 };
 
@@ -713,6 +738,19 @@ const buildMemberPermissionRules = () => {
     ProjectPermissionSub.Cmek
   );
 
+  can(
+    [
+      ProjectPermissionSecretSyncActions.Create,
+      ProjectPermissionSecretSyncActions.Edit,
+      ProjectPermissionSecretSyncActions.Delete,
+      ProjectPermissionSecretSyncActions.Read,
+      ProjectPermissionSecretSyncActions.SyncSecrets,
+      ProjectPermissionSecretSyncActions.ImportSecrets,
+      ProjectPermissionSecretSyncActions.RemoveSecrets
+    ],
+    ProjectPermissionSub.SecretSyncs
+  );
+
   return rules;
 };
 
@@ -746,6 +784,7 @@ const buildViewerPermissionRules = () => {
   can(ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificateAuthorities);
   can(ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificates);
   can(ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificateTemplates);
+  can(ProjectPermissionSecretSyncActions.Read, ProjectPermissionSub.SecretSyncs);
 
   return rules;
 };
diff --git a/backend/src/keystore/keystore.ts b/backend/src/keystore/keystore.ts
index 723a22817a..dbfdfd063c 100644
--- a/backend/src/keystore/keystore.ts
+++ b/backend/src/keystore/keystore.ts
@@ -23,6 +23,8 @@ export const KeyStorePrefixes = {
     `sync-integration-mutex-${projectId}-${environmentSlug}-${secretPath}` as const,
   SyncSecretIntegrationLastRunTimestamp: (projectId: string, environmentSlug: string, secretPath: string) =>
     `sync-integration-last-run-${projectId}-${environmentSlug}-${secretPath}` as const,
+  SecretSyncLock: (syncId: string) => `secret-sync-mutex-${syncId}` as const,
+  SecretSyncLastRunTimestamp: (syncId: string) => `secret-sync-last-run-${syncId}` as const,
   IdentityAccessTokenStatusUpdate: (identityAccessTokenId: string) =>
     `identity-access-token-status:${identityAccessTokenId}`,
   ServiceTokenStatusUpdate: (serviceTokenId: string) => `service-token-status:${serviceTokenId}`
@@ -30,6 +32,7 @@ export const KeyStorePrefixes = {
 
 export const KeyStoreTtls = {
   SetSyncSecretIntegrationLastRunTimestampInSeconds: 60,
+  SetSecretSyncLastRunTimestampInSeconds: 60,
   AccessTokenStatusUpdateInSeconds: 120
 };
 
diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts
index e6fa7344a2..800788179d 100644
--- a/backend/src/lib/api-docs/constants.ts
+++ b/backend/src/lib/api-docs/constants.ts
@@ -1,5 +1,7 @@
 import { AppConnection } from "@app/services/app-connection/app-connection-enums";
 import { APP_CONNECTION_NAME_MAP } from "@app/services/app-connection/app-connection-maps";
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+import { SECRET_SYNC_CONNECTION_MAP, SECRET_SYNC_NAME_MAP } from "@app/services/secret-sync/secret-sync-maps";
 
 export const GROUPS = {
   CREATE: {
@@ -1643,6 +1645,83 @@ export const AppConnections = {
     };
   },
   DELETE: (app: AppConnection) => ({
-    connectionId: `The ID of the ${APP_CONNECTION_NAME_MAP[app]} connection to be deleted.`
+    connectionId: `The ID of the ${APP_CONNECTION_NAME_MAP[app]} Connection to be deleted.`
   })
 };
+
+export const SecretSyncs = {
+  LIST: (destination?: SecretSync) => ({
+    projectId: `The ID of the project to list ${destination ? SECRET_SYNC_NAME_MAP[destination] : "Secret"} Syncs from.`
+  }),
+  GET_BY_ID: (destination: SecretSync) => ({
+    syncId: `The ID of the ${SECRET_SYNC_NAME_MAP[destination]} Sync to retrieve.`
+  }),
+  GET_BY_NAME: (destination: SecretSync) => ({
+    syncName: `The name of the ${SECRET_SYNC_NAME_MAP[destination]} Sync to retrieve.`,
+    projectId: `The ID of the project the ${SECRET_SYNC_NAME_MAP[destination]} Sync is associated with.`
+  }),
+  CREATE: (destination: SecretSync) => {
+    const destinationName = SECRET_SYNC_NAME_MAP[destination];
+    return {
+      name: `The name of the ${destinationName} Sync to create. Must be slug-friendly.`,
+      description: `An optional description for the ${destinationName} Sync.`,
+      projectId: "The ID of the project to create the sync in.",
+      environment: `The slug of the project environment to sync secrets from.`,
+      secretPath: `The folder path to sync secrets from.`,
+      connectionId: `The ID of the ${
+        APP_CONNECTION_NAME_MAP[SECRET_SYNC_CONNECTION_MAP[destination]]
+      } Connection to use for syncing.`,
+      isAutoSyncEnabled: `Whether secrets should be automatically synced when changes occur at the source location or not.`,
+      syncOptions: "Optional parameters to modify how secrets are synced."
+    };
+  },
+  UPDATE: (destination: SecretSync) => {
+    const destinationName = SECRET_SYNC_NAME_MAP[destination];
+    return {
+      syncId: `The ID of the ${destinationName} Sync to be updated.`,
+      connectionId: `The updated ID of the ${
+        APP_CONNECTION_NAME_MAP[SECRET_SYNC_CONNECTION_MAP[destination]]
+      } Connection to use for syncing.`,
+      name: `The updated name of the ${destinationName} Sync. Must be slug-friendly.`,
+      environment: `The updated slug of the project environment to sync secrets from.`,
+      secretPath: `The updated folder path to sync secrets from.`,
+      description: `The updated description of the ${destinationName} Sync.`,
+      isAutoSyncEnabled: `Whether secrets should be automatically synced when changes occur at the source location or not.`,
+      syncOptions: "Optional parameters to modify how secrets are synced."
+    };
+  },
+  DELETE: (destination: SecretSync) => ({
+    syncId: `The ID of the ${SECRET_SYNC_NAME_MAP[destination]} Sync to be deleted.`,
+    removeSecrets: `Whether previously synced secrets should be removed prior to deletion.`
+  }),
+  SYNC_SECRETS: (destination: SecretSync) => ({
+    syncId: `The ID of the ${SECRET_SYNC_NAME_MAP[destination]} Sync to trigger a sync for.`
+  }),
+  IMPORT_SECRETS: (destination: SecretSync) => ({
+    syncId: `The ID of the ${SECRET_SYNC_NAME_MAP[destination]} Sync to trigger importing secrets for.`,
+    importBehavior: `Specify whether Infisical should prioritize secret values from Infisical or ${SECRET_SYNC_NAME_MAP[destination]}.`
+  }),
+  REMOVE_SECRETS: (destination: SecretSync) => ({
+    syncId: `The ID of the ${SECRET_SYNC_NAME_MAP[destination]} Sync to trigger removing secrets for.`
+  }),
+  SYNC_OPTIONS: (destination: SecretSync) => {
+    const destinationName = SECRET_SYNC_NAME_MAP[destination];
+    return {
+      INITIAL_SYNC_BEHAVIOR: `Specify how Infisical should resolve the initial sync to the ${destinationName} destination.`,
+      PREPEND_PREFIX: `Optionally prepend a prefix to your secrets' keys when syncing to ${destinationName}.`,
+      APPEND_SUFFIX: `Optionally append a suffix to your secrets' keys when syncing to ${destinationName}.`
+    };
+  },
+  DESTINATION_CONFIG: {
+    AWS_PARAMETER_STORE: {
+      REGION: "The AWS region to sync secrets to.",
+      PATH: "The Parameter Store path to sync secrets to."
+    },
+    GITHUB: {
+      ORG: "The name of the GitHub organization.",
+      OWNER: "The name of the GitHub account owner of the repository.",
+      REPO: "The name of the GitHub repository.",
+      ENV: "The name of the GitHub environment."
+    }
+  }
+};
diff --git a/backend/src/queue/queue-service.ts b/backend/src/queue/queue-service.ts
index 330193052c..f9aec5881d 100644
--- a/backend/src/queue/queue-service.ts
+++ b/backend/src/queue/queue-service.ts
@@ -15,6 +15,12 @@ import {
   TIntegrationSyncPayload,
   TSyncSecretsDTO
 } from "@app/services/secret/secret-types";
+import {
+  TQueueSecretSyncImportSecretsByIdDTO,
+  TQueueSecretSyncRemoveSecretsByIdDTO,
+  TQueueSecretSyncSyncSecretsByIdDTO,
+  TQueueSendSecretSyncActionFailedNotificationsDTO
+} from "@app/services/secret-sync/secret-sync-types";
 
 export enum QueueName {
   SecretRotation = "secret-rotation",
@@ -36,7 +42,8 @@ export enum QueueName {
   SecretSync = "secret-sync", // parent queue to push integration sync, webhook, and secret replication
   ProjectV3Migration = "project-v3-migration",
   AccessTokenStatusUpdate = "access-token-status-update",
-  ImportSecretsFromExternalSource = "import-secrets-from-external-source"
+  ImportSecretsFromExternalSource = "import-secrets-from-external-source",
+  AppConnectionSecretSync = "app-connection-secret-sync"
 }
 
 export enum QueueJobs {
@@ -61,7 +68,11 @@ export enum QueueJobs {
   ProjectV3Migration = "project-v3-migration",
   IdentityAccessTokenStatusUpdate = "identity-access-token-status-update",
   ServiceTokenStatusUpdate = "service-token-status-update",
-  ImportSecretsFromExternalSource = "import-secrets-from-external-source"
+  ImportSecretsFromExternalSource = "import-secrets-from-external-source",
+  SecretSyncSyncSecrets = "secret-sync-sync-secrets",
+  SecretSyncImportSecrets = "secret-sync-import-secrets",
+  SecretSyncRemoveSecrets = "secret-sync-remove-secrets",
+  SecretSyncSendActionFailedNotifications = "secret-sync-send-action-failed-notifications"
 }
 
 export type TQueueJobTypes = {
@@ -184,6 +195,23 @@ export type TQueueJobTypes = {
       };
     };
   };
+  [QueueName.AppConnectionSecretSync]:
+    | {
+        name: QueueJobs.SecretSyncSyncSecrets;
+        payload: TQueueSecretSyncSyncSecretsByIdDTO;
+      }
+    | {
+        name: QueueJobs.SecretSyncImportSecrets;
+        payload: TQueueSecretSyncImportSecretsByIdDTO;
+      }
+    | {
+        name: QueueJobs.SecretSyncRemoveSecrets;
+        payload: TQueueSecretSyncRemoveSecretsByIdDTO;
+      }
+    | {
+        name: QueueJobs.SecretSyncSendActionFailedNotifications;
+        payload: TQueueSendSecretSyncActionFailedNotificationsDTO;
+      };
 };
 
 export type TQueueServiceFactory = ReturnType<typeof queueServiceFactory>;
diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts
index 3e5575daa5..442f110808 100644
--- a/backend/src/server/routes/index.ts
+++ b/backend/src/server/routes/index.ts
@@ -196,6 +196,9 @@ import { secretImportDALFactory } from "@app/services/secret-import/secret-impor
 import { secretImportServiceFactory } from "@app/services/secret-import/secret-import-service";
 import { secretSharingDALFactory } from "@app/services/secret-sharing/secret-sharing-dal";
 import { secretSharingServiceFactory } from "@app/services/secret-sharing/secret-sharing-service";
+import { secretSyncDALFactory } from "@app/services/secret-sync/secret-sync-dal";
+import { secretSyncQueueFactory } from "@app/services/secret-sync/secret-sync-queue";
+import { secretSyncServiceFactory } from "@app/services/secret-sync/secret-sync-service";
 import { secretTagDALFactory } from "@app/services/secret-tag/secret-tag-dal";
 import { secretTagServiceFactory } from "@app/services/secret-tag/secret-tag-service";
 import { secretV2BridgeDALFactory } from "@app/services/secret-v2-bridge/secret-v2-bridge-dal";
@@ -318,6 +321,7 @@ export const registerRoutes = async (
   const trustedIpDAL = trustedIpDALFactory(db);
   const telemetryDAL = telemetryDALFactory(db);
   const appConnectionDAL = appConnectionDALFactory(db);
+  const secretSyncDAL = secretSyncDALFactory(db, folderDAL);
 
   // ee db layer ops
   const permissionDAL = permissionDALFactory(db);
@@ -824,6 +828,29 @@ export const registerRoutes = async (
     kmsService
   });
 
+  const secretSyncQueue = secretSyncQueueFactory({
+    queueService,
+    secretSyncDAL,
+    folderDAL,
+    secretImportDAL,
+    secretV2BridgeDAL,
+    kmsService,
+    keyStore,
+    auditLogService,
+    smtpService,
+    projectDAL,
+    projectMembershipDAL,
+    projectBotDAL,
+    secretDAL,
+    secretBlindIndexDAL,
+    secretVersionDAL,
+    secretTagDAL,
+    secretVersionTagDAL,
+    secretVersionV2BridgeDAL,
+    secretVersionTagV2BridgeDAL,
+    resourceMetadataDAL
+  });
+
   const secretQueueService = secretQueueFactory({
     keyStore,
     queueService,
@@ -858,7 +885,8 @@ export const registerRoutes = async (
     projectKeyDAL,
     projectUserMembershipRoleDAL,
     orgService,
-    resourceMetadataDAL
+    resourceMetadataDAL,
+    secretSyncQueue
   });
 
   const projectService = projectServiceFactory({
@@ -1369,8 +1397,17 @@ export const registerRoutes = async (
   const appConnectionService = appConnectionServiceFactory({
     appConnectionDAL,
     permissionService,
-    kmsService,
-    licenseService
+    kmsService
+  });
+
+  const secretSyncService = secretSyncServiceFactory({
+    secretSyncDAL,
+    permissionService,
+    appConnectionService,
+    folderDAL,
+    secretSyncQueue,
+    projectBotService,
+    keyStore
   });
 
   await superAdminService.initServerCfg();
@@ -1470,7 +1507,8 @@ export const registerRoutes = async (
     externalGroupOrgRoleMapping: externalGroupOrgRoleMappingService,
     projectTemplate: projectTemplateService,
     totp: totpService,
-    appConnection: appConnectionService
+    appConnection: appConnectionService,
+    secretSync: secretSyncService
   });
 
   const cronJobs: CronJob[] = [];
diff --git a/backend/src/server/routes/v1/app-connection-routers/apps/app-connection-endpoints.ts b/backend/src/server/routes/v1/app-connection-routers/app-connection-endpoints.ts
similarity index 80%
rename from backend/src/server/routes/v1/app-connection-routers/apps/app-connection-endpoints.ts
rename to backend/src/server/routes/v1/app-connection-routers/app-connection-endpoints.ts
index ec3b633a19..41a87feb5a 100644
--- a/backend/src/server/routes/v1/app-connection-routers/apps/app-connection-endpoints.ts
+++ b/backend/src/server/routes/v1/app-connection-routers/app-connection-endpoints.ts
@@ -15,7 +15,7 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
   app,
   createSchema,
   updateSchema,
-  responseSchema
+  sanitizedResponseSchema
 }: {
   app: AppConnection;
   server: FastifyZodProvider;
@@ -26,7 +26,7 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
     description?: string | null;
   }>;
   updateSchema: z.ZodType<{ name?: string; credentials?: I["credentials"]; description?: string | null }>;
-  responseSchema: z.ZodTypeAny;
+  sanitizedResponseSchema: z.ZodTypeAny;
 }) => {
   const appName = APP_CONNECTION_NAME_MAP[app];
 
@@ -39,7 +39,7 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
     schema: {
       description: `List the ${appName} Connections for the current organization.`,
       response: {
-        200: z.object({ appConnections: responseSchema.array() })
+        200: z.object({ appConnections: sanitizedResponseSchema.array() })
       }
     },
     onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
@@ -63,6 +63,44 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
     }
   });
 
+  server.route({
+    method: "GET",
+    url: "/available",
+    config: {
+      rateLimit: readLimit
+    },
+    schema: {
+      description: `List the ${appName} Connections the current user has permission to establish connections with.`,
+      response: {
+        200: z.object({
+          appConnections: z.object({ app: z.literal(app), name: z.string(), id: z.string().uuid() }).array()
+        })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const appConnections = await server.services.appConnection.listAvailableAppConnectionsForUser(
+        app,
+        req.permission
+      );
+
+      await server.services.auditLog.createAuditLog({
+        ...req.auditLogInfo,
+        orgId: req.permission.orgId,
+        event: {
+          type: EventType.GET_AVAILABLE_APP_CONNECTIONS_DETAILS,
+          metadata: {
+            app,
+            count: appConnections.length,
+            connectionIds: appConnections.map((connection) => connection.id)
+          }
+        }
+      });
+
+      return { appConnections };
+    }
+  });
+
   server.route({
     method: "GET",
     url: "/:connectionId",
@@ -75,7 +113,7 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
         connectionId: z.string().uuid().describe(AppConnections.GET_BY_ID(app).connectionId)
       }),
       response: {
-        200: z.object({ appConnection: responseSchema })
+        200: z.object({ appConnection: sanitizedResponseSchema })
       }
     },
     onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
@@ -105,7 +143,7 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
 
   server.route({
     method: "GET",
-    url: `/name/:connectionName`,
+    url: `/connection-name/:connectionName`,
     config: {
       rateLimit: readLimit
     },
@@ -114,11 +152,12 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
       params: z.object({
         connectionName: z
           .string()
-          .min(0, "Connection name required")
+          .trim()
+          .min(1, "Connection name required")
           .describe(AppConnections.GET_BY_NAME(app).connectionName)
       }),
       response: {
-        200: z.object({ appConnection: responseSchema })
+        200: z.object({ appConnection: sanitizedResponseSchema })
       }
     },
     onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
@@ -158,7 +197,7 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
       } ${appName} Connection for the current organization.`,
       body: createSchema,
       response: {
-        200: z.object({ appConnection: responseSchema })
+        200: z.object({ appConnection: sanitizedResponseSchema })
       }
     },
     onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
@@ -168,7 +207,7 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
       const appConnection = (await server.services.appConnection.createAppConnection(
         { name, method, app, credentials, description },
         req.permission
-      )) as TAppConnection;
+      )) as T;
 
       await server.services.auditLog.createAuditLog({
         ...req.auditLogInfo,
@@ -201,7 +240,7 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
       }),
       body: updateSchema,
       response: {
-        200: z.object({ appConnection: responseSchema })
+        200: z.object({ appConnection: sanitizedResponseSchema })
       }
     },
     onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
@@ -244,7 +283,7 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
         connectionId: z.string().uuid().describe(AppConnections.DELETE(app).connectionId)
       }),
       response: {
-        200: z.object({ appConnection: responseSchema })
+        200: z.object({ appConnection: sanitizedResponseSchema })
       }
     },
     onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
diff --git a/backend/src/server/routes/v1/app-connection-routers/apps/github-connection-router.ts b/backend/src/server/routes/v1/app-connection-routers/apps/github-connection-router.ts
deleted file mode 100644
index 273d4b9e16..0000000000
--- a/backend/src/server/routes/v1/app-connection-routers/apps/github-connection-router.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { AppConnection } from "@app/services/app-connection/app-connection-enums";
-import {
-  CreateGitHubConnectionSchema,
-  SanitizedGitHubConnectionSchema,
-  UpdateGitHubConnectionSchema
-} from "@app/services/app-connection/github";
-
-import { registerAppConnectionEndpoints } from "./app-connection-endpoints";
-
-export const registerGitHubConnectionRouter = async (server: FastifyZodProvider) =>
-  registerAppConnectionEndpoints({
-    app: AppConnection.GitHub,
-    server,
-    responseSchema: SanitizedGitHubConnectionSchema,
-    createSchema: CreateGitHubConnectionSchema,
-    updateSchema: UpdateGitHubConnectionSchema
-  });
diff --git a/backend/src/server/routes/v1/app-connection-routers/apps/index.ts b/backend/src/server/routes/v1/app-connection-routers/apps/index.ts
deleted file mode 100644
index b56a65f508..0000000000
--- a/backend/src/server/routes/v1/app-connection-routers/apps/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { registerAwsConnectionRouter } from "@app/server/routes/v1/app-connection-routers/apps/aws-connection-router";
-import { registerGitHubConnectionRouter } from "@app/server/routes/v1/app-connection-routers/apps/github-connection-router";
-import { AppConnection } from "@app/services/app-connection/app-connection-enums";
-
-export const APP_CONNECTION_REGISTER_MAP: Record<AppConnection, (server: FastifyZodProvider) => Promise<void>> = {
-  [AppConnection.AWS]: registerAwsConnectionRouter,
-  [AppConnection.GitHub]: registerGitHubConnectionRouter
-};
diff --git a/backend/src/server/routes/v1/app-connection-routers/apps/aws-connection-router.ts b/backend/src/server/routes/v1/app-connection-routers/aws-connection-router.ts
similarity index 90%
rename from backend/src/server/routes/v1/app-connection-routers/apps/aws-connection-router.ts
rename to backend/src/server/routes/v1/app-connection-routers/aws-connection-router.ts
index 189ca4fbdf..87ed022a28 100644
--- a/backend/src/server/routes/v1/app-connection-routers/apps/aws-connection-router.ts
+++ b/backend/src/server/routes/v1/app-connection-routers/aws-connection-router.ts
@@ -11,7 +11,7 @@ export const registerAwsConnectionRouter = async (server: FastifyZodProvider) =>
   registerAppConnectionEndpoints({
     app: AppConnection.AWS,
     server,
-    responseSchema: SanitizedAwsConnectionSchema,
+    sanitizedResponseSchema: SanitizedAwsConnectionSchema,
     createSchema: CreateAwsConnectionSchema,
     updateSchema: UpdateAwsConnectionSchema
   });
diff --git a/backend/src/server/routes/v1/app-connection-routers/github-connection-router.ts b/backend/src/server/routes/v1/app-connection-routers/github-connection-router.ts
new file mode 100644
index 0000000000..9c33f3fad2
--- /dev/null
+++ b/backend/src/server/routes/v1/app-connection-routers/github-connection-router.ts
@@ -0,0 +1,117 @@
+import { z } from "zod";
+
+import { readLimit } from "@app/server/config/rateLimiter";
+import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
+import { AppConnection } from "@app/services/app-connection/app-connection-enums";
+import {
+  CreateGitHubConnectionSchema,
+  SanitizedGitHubConnectionSchema,
+  UpdateGitHubConnectionSchema
+} from "@app/services/app-connection/github";
+import { AuthMode } from "@app/services/auth/auth-type";
+
+import { registerAppConnectionEndpoints } from "./app-connection-endpoints";
+
+export const registerGitHubConnectionRouter = async (server: FastifyZodProvider) => {
+  registerAppConnectionEndpoints({
+    app: AppConnection.GitHub,
+    server,
+    sanitizedResponseSchema: SanitizedGitHubConnectionSchema,
+    createSchema: CreateGitHubConnectionSchema,
+    updateSchema: UpdateGitHubConnectionSchema
+  });
+
+  // The below endpoints are not exposed and for Infisical App use
+
+  server.route({
+    method: "GET",
+    url: `/:connectionId/repositories`,
+    config: {
+      rateLimit: readLimit
+    },
+    schema: {
+      params: z.object({
+        connectionId: z.string().uuid()
+      }),
+      response: {
+        200: z.object({
+          repositories: z
+            .object({ id: z.number(), name: z.string(), owner: z.object({ login: z.string(), id: z.number() }) })
+            .array()
+        })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const { connectionId } = req.params;
+
+      const repositories = await server.services.appConnection.github.listRepositories(connectionId, req.permission);
+
+      return { repositories };
+    }
+  });
+
+  server.route({
+    method: "GET",
+    url: `/:connectionId/organizations`,
+    config: {
+      rateLimit: readLimit
+    },
+    schema: {
+      params: z.object({
+        connectionId: z.string().uuid()
+      }),
+      response: {
+        200: z.object({
+          organizations: z.object({ id: z.number(), login: z.string() }).array()
+        })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const { connectionId } = req.params;
+
+      const organizations = await server.services.appConnection.github.listOrganizations(connectionId, req.permission);
+
+      return { organizations };
+    }
+  });
+
+  server.route({
+    method: "GET",
+    url: `/:connectionId/environments`,
+    config: {
+      rateLimit: readLimit
+    },
+    schema: {
+      params: z.object({
+        connectionId: z.string().uuid()
+      }),
+      querystring: z.object({
+        repo: z.string().min(1, "Repository name is required"),
+        owner: z.string().min(1, "Repository owner name is required")
+      }),
+      response: {
+        200: z.object({
+          environments: z.object({ id: z.number(), name: z.string() }).array()
+        })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const { connectionId } = req.params;
+      const { repo, owner } = req.query;
+
+      const environments = await server.services.appConnection.github.listEnvironments(
+        {
+          connectionId,
+          repo,
+          owner
+        },
+        req.permission
+      );
+
+      return { environments };
+    }
+  });
+};
diff --git a/backend/src/server/routes/v1/app-connection-routers/index.ts b/backend/src/server/routes/v1/app-connection-routers/index.ts
index 7200574495..2570cb3ada 100644
--- a/backend/src/server/routes/v1/app-connection-routers/index.ts
+++ b/backend/src/server/routes/v1/app-connection-routers/index.ts
@@ -1,2 +1,12 @@
+import { AppConnection } from "@app/services/app-connection/app-connection-enums";
+
+import { registerAwsConnectionRouter } from "./aws-connection-router";
+import { registerGitHubConnectionRouter } from "./github-connection-router";
+
 export * from "./app-connection-router";
-export * from "./apps";
+
+export const APP_CONNECTION_REGISTER_ROUTER_MAP: Record<AppConnection, (server: FastifyZodProvider) => Promise<void>> =
+  {
+    [AppConnection.AWS]: registerAwsConnectionRouter,
+    [AppConnection.GitHub]: registerGitHubConnectionRouter
+  };
diff --git a/backend/src/server/routes/v1/index.ts b/backend/src/server/routes/v1/index.ts
index 7fae1d1f99..e3f6c7f2e3 100644
--- a/backend/src/server/routes/v1/index.ts
+++ b/backend/src/server/routes/v1/index.ts
@@ -1,6 +1,10 @@
-import { APP_CONNECTION_REGISTER_MAP, registerAppConnectionRouter } from "@app/server/routes/v1/app-connection-routers";
+import {
+  APP_CONNECTION_REGISTER_ROUTER_MAP,
+  registerAppConnectionRouter
+} from "@app/server/routes/v1/app-connection-routers";
 import { registerCmekRouter } from "@app/server/routes/v1/cmek-router";
 import { registerDashboardRouter } from "@app/server/routes/v1/dashboard-router";
+import { registerSecretSyncRouter, SECRET_SYNC_REGISTER_ROUTER_MAP } from "@app/server/routes/v1/secret-sync-routers";
 
 import { registerAdminRouter } from "./admin-router";
 import { registerAuthRoutes } from "./auth-router";
@@ -113,12 +117,28 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
   await server.register(registerExternalGroupOrgRoleMappingRouter, { prefix: "/external-group-mappings" });
 
   await server.register(
-    async (appConnectionsRouter) => {
-      await appConnectionsRouter.register(registerAppConnectionRouter);
-      for await (const [app, router] of Object.entries(APP_CONNECTION_REGISTER_MAP)) {
-        await appConnectionsRouter.register(router, { prefix: `/${app}` });
+    async (appConnectionRouter) => {
+      // register generic app connection endpoints
+      await appConnectionRouter.register(registerAppConnectionRouter);
+
+      // register service specific endpoints (app-connections/aws, app-connections/github, etc.)
+      for await (const [app, router] of Object.entries(APP_CONNECTION_REGISTER_ROUTER_MAP)) {
+        await appConnectionRouter.register(router, { prefix: `/${app}` });
       }
     },
     { prefix: "/app-connections" }
   );
+
+  await server.register(
+    async (secretSyncRouter) => {
+      // register generic secret sync endpoints
+      await secretSyncRouter.register(registerSecretSyncRouter);
+
+      // register service specific secret sync endpoints (secret-syncs/aws-parameter-store, secret-syncs/github, etc.)
+      for await (const [destination, router] of Object.entries(SECRET_SYNC_REGISTER_ROUTER_MAP)) {
+        await secretSyncRouter.register(router, { prefix: `/${destination}` });
+      }
+    },
+    { prefix: "/secret-syncs" }
+  );
 };
diff --git a/backend/src/server/routes/v1/secret-sync-routers/aws-parameter-store-sync-router.ts b/backend/src/server/routes/v1/secret-sync-routers/aws-parameter-store-sync-router.ts
new file mode 100644
index 0000000000..8f02b9e6e9
--- /dev/null
+++ b/backend/src/server/routes/v1/secret-sync-routers/aws-parameter-store-sync-router.ts
@@ -0,0 +1,17 @@
+import {
+  AwsParameterStoreSyncSchema,
+  CreateAwsParameterStoreSyncSchema,
+  UpdateAwsParameterStoreSyncSchema
+} from "@app/services/secret-sync/aws-parameter-store";
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+
+import { registerSyncSecretsEndpoints } from "./secret-sync-endpoints";
+
+export const registerAwsParameterStoreSyncRouter = async (server: FastifyZodProvider) =>
+  registerSyncSecretsEndpoints({
+    destination: SecretSync.AWSParameterStore,
+    server,
+    responseSchema: AwsParameterStoreSyncSchema,
+    createSchema: CreateAwsParameterStoreSyncSchema,
+    updateSchema: UpdateAwsParameterStoreSyncSchema
+  });
diff --git a/backend/src/server/routes/v1/secret-sync-routers/github-sync-router.ts b/backend/src/server/routes/v1/secret-sync-routers/github-sync-router.ts
new file mode 100644
index 0000000000..a84d70354b
--- /dev/null
+++ b/backend/src/server/routes/v1/secret-sync-routers/github-sync-router.ts
@@ -0,0 +1,13 @@
+import { CreateGitHubSyncSchema, GitHubSyncSchema, UpdateGitHubSyncSchema } from "@app/services/secret-sync/github";
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+
+import { registerSyncSecretsEndpoints } from "./secret-sync-endpoints";
+
+export const registerGitHubSyncRouter = async (server: FastifyZodProvider) =>
+  registerSyncSecretsEndpoints({
+    destination: SecretSync.GitHub,
+    server,
+    responseSchema: GitHubSyncSchema,
+    createSchema: CreateGitHubSyncSchema,
+    updateSchema: UpdateGitHubSyncSchema
+  });
diff --git a/backend/src/server/routes/v1/secret-sync-routers/index.ts b/backend/src/server/routes/v1/secret-sync-routers/index.ts
new file mode 100644
index 0000000000..ecc21b7764
--- /dev/null
+++ b/backend/src/server/routes/v1/secret-sync-routers/index.ts
@@ -0,0 +1,11 @@
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+
+import { registerAwsParameterStoreSyncRouter } from "./aws-parameter-store-sync-router";
+import { registerGitHubSyncRouter } from "./github-sync-router";
+
+export * from "./secret-sync-router";
+
+export const SECRET_SYNC_REGISTER_ROUTER_MAP: Record<SecretSync, (server: FastifyZodProvider) => Promise<void>> = {
+  [SecretSync.AWSParameterStore]: registerAwsParameterStoreSyncRouter,
+  [SecretSync.GitHub]: registerGitHubSyncRouter
+};
diff --git a/backend/src/server/routes/v1/secret-sync-routers/secret-sync-endpoints.ts b/backend/src/server/routes/v1/secret-sync-routers/secret-sync-endpoints.ts
new file mode 100644
index 0000000000..31826f86f8
--- /dev/null
+++ b/backend/src/server/routes/v1/secret-sync-routers/secret-sync-endpoints.ts
@@ -0,0 +1,408 @@
+import { z } from "zod";
+
+import { EventType } from "@app/ee/services/audit-log/audit-log-types";
+import { SecretSyncs } from "@app/lib/api-docs";
+import { startsWithVowel } from "@app/lib/fn";
+import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
+import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
+import { AuthMode } from "@app/services/auth/auth-type";
+import { SecretSync, SecretSyncImportBehavior } from "@app/services/secret-sync/secret-sync-enums";
+import { SECRET_SYNC_NAME_MAP } from "@app/services/secret-sync/secret-sync-maps";
+import { TSecretSync, TSecretSyncInput } from "@app/services/secret-sync/secret-sync-types";
+
+export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TSecretSyncInput>({
+  server,
+  destination,
+  createSchema,
+  updateSchema,
+  responseSchema
+}: {
+  destination: SecretSync;
+  server: FastifyZodProvider;
+  createSchema: z.ZodType<{
+    name: string;
+    environment: string;
+    secretPath: string;
+    projectId: string;
+    connectionId: string;
+    destinationConfig: I["destinationConfig"];
+    syncOptions: I["syncOptions"];
+    description?: string | null;
+    isAutoSyncEnabled?: boolean;
+  }>;
+  updateSchema: z.ZodType<{
+    connectionId?: string;
+    name?: string;
+    environment?: string;
+    secretPath?: string;
+    destinationConfig?: I["destinationConfig"];
+    syncOptions?: I["syncOptions"];
+    description?: string | null;
+    isAutoSyncEnabled?: boolean;
+  }>;
+  responseSchema: z.ZodTypeAny;
+}) => {
+  const destinationName = SECRET_SYNC_NAME_MAP[destination];
+
+  server.route({
+    method: "GET",
+    url: `/`,
+    config: {
+      rateLimit: readLimit
+    },
+    schema: {
+      description: `List the ${destinationName} Syncs for the specified project.`,
+      querystring: z.object({
+        projectId: z.string().trim().min(1, "Project ID required").describe(SecretSyncs.LIST(destination).projectId)
+      }),
+      response: {
+        200: z.object({ secretSyncs: responseSchema.array() })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const {
+        query: { projectId }
+      } = req;
+
+      const secretSyncs = (await server.services.secretSync.listSecretSyncsByProjectId(
+        { projectId, destination },
+        req.permission
+      )) as T[];
+
+      await server.services.auditLog.createAuditLog({
+        ...req.auditLogInfo,
+        projectId,
+        event: {
+          type: EventType.GET_SECRET_SYNCS,
+          metadata: {
+            destination,
+            count: secretSyncs.length,
+            syncIds: secretSyncs.map((connection) => connection.id)
+          }
+        }
+      });
+
+      return { secretSyncs };
+    }
+  });
+
+  server.route({
+    method: "GET",
+    url: "/:syncId",
+    config: {
+      rateLimit: readLimit
+    },
+    schema: {
+      description: `Get the specified ${destinationName} Sync by ID.`,
+      params: z.object({
+        syncId: z.string().uuid().describe(SecretSyncs.GET_BY_ID(destination).syncId)
+      }),
+      response: {
+        200: z.object({ secretSync: responseSchema })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const { syncId } = req.params;
+
+      const secretSync = (await server.services.secretSync.findSecretSyncById(
+        { syncId, destination },
+        req.permission
+      )) as T;
+
+      await server.services.auditLog.createAuditLog({
+        ...req.auditLogInfo,
+        projectId: secretSync.projectId,
+        event: {
+          type: EventType.GET_SECRET_SYNC,
+          metadata: {
+            syncId,
+            destination
+          }
+        }
+      });
+
+      return { secretSync };
+    }
+  });
+
+  server.route({
+    method: "GET",
+    url: `/sync-name/:syncName`,
+    config: {
+      rateLimit: readLimit
+    },
+    schema: {
+      description: `Get the specified ${destinationName} Sync by name and project ID.`,
+      params: z.object({
+        syncName: z.string().trim().min(1, "Sync name required").describe(SecretSyncs.GET_BY_NAME(destination).syncName)
+      }),
+      querystring: z.object({
+        projectId: z
+          .string()
+          .trim()
+          .min(1, "Project ID required")
+          .describe(SecretSyncs.GET_BY_NAME(destination).projectId)
+      }),
+      response: {
+        200: z.object({ secretSync: responseSchema })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const { syncName } = req.params;
+      const { projectId } = req.query;
+
+      const secretSync = (await server.services.secretSync.findSecretSyncByName(
+        { syncName, projectId, destination },
+        req.permission
+      )) as T;
+
+      await server.services.auditLog.createAuditLog({
+        ...req.auditLogInfo,
+        projectId,
+        event: {
+          type: EventType.GET_SECRET_SYNC,
+          metadata: {
+            syncId: secretSync.id,
+            destination
+          }
+        }
+      });
+
+      return { secretSync };
+    }
+  });
+
+  server.route({
+    method: "POST",
+    url: "/",
+    config: {
+      rateLimit: writeLimit
+    },
+    schema: {
+      description: `Create ${
+        startsWithVowel(destinationName) ? "an" : "a"
+      } ${destinationName} Sync for the specified project environment.`,
+      body: createSchema,
+      response: {
+        200: z.object({ secretSync: responseSchema })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const secretSync = (await server.services.secretSync.createSecretSync(
+        { ...req.body, destination },
+        req.permission
+      )) as T;
+
+      await server.services.auditLog.createAuditLog({
+        ...req.auditLogInfo,
+        projectId: secretSync.projectId,
+        event: {
+          type: EventType.CREATE_SECRET_SYNC,
+          metadata: {
+            syncId: secretSync.id,
+            destination,
+            ...req.body
+          }
+        }
+      });
+
+      return { secretSync };
+    }
+  });
+
+  server.route({
+    method: "PATCH",
+    url: "/:syncId",
+    config: {
+      rateLimit: writeLimit
+    },
+    schema: {
+      description: `Update the specified ${destinationName} Sync.`,
+      params: z.object({
+        syncId: z.string().uuid().describe(SecretSyncs.UPDATE(destination).syncId)
+      }),
+      body: updateSchema,
+      response: {
+        200: z.object({ secretSync: responseSchema })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const { syncId } = req.params;
+
+      const secretSync = (await server.services.secretSync.updateSecretSync(
+        { ...req.body, syncId, destination },
+        req.permission
+      )) as T;
+
+      await server.services.auditLog.createAuditLog({
+        ...req.auditLogInfo,
+        projectId: secretSync.projectId,
+        event: {
+          type: EventType.UPDATE_SECRET_SYNC,
+          metadata: {
+            syncId,
+            destination,
+            ...req.body
+          }
+        }
+      });
+
+      return { secretSync };
+    }
+  });
+
+  server.route({
+    method: "DELETE",
+    url: `/:syncId`,
+    config: {
+      rateLimit: writeLimit
+    },
+    schema: {
+      description: `Delete the specified ${destinationName} Sync.`,
+      params: z.object({
+        syncId: z.string().uuid().describe(SecretSyncs.DELETE(destination).syncId)
+      }),
+      querystring: z.object({
+        removeSecrets: z
+          .enum(["true", "false"])
+          .default("false")
+          .transform((value) => value === "true")
+          .describe(SecretSyncs.DELETE(destination).removeSecrets)
+      }),
+      response: {
+        200: z.object({ secretSync: responseSchema })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const { syncId } = req.params;
+      const { removeSecrets } = req.query;
+
+      const secretSync = (await server.services.secretSync.deleteSecretSync(
+        { destination, syncId, removeSecrets },
+        req.permission
+      )) as T;
+
+      await server.services.auditLog.createAuditLog({
+        ...req.auditLogInfo,
+        orgId: req.permission.orgId,
+        event: {
+          type: EventType.DELETE_SECRET_SYNC,
+          metadata: {
+            destination,
+            syncId,
+            removeSecrets
+          }
+        }
+      });
+
+      return { secretSync };
+    }
+  });
+
+  server.route({
+    method: "POST",
+    url: "/:syncId/sync-secrets",
+    config: {
+      rateLimit: writeLimit
+    },
+    schema: {
+      description: `Trigger a sync for the specified ${destinationName} Sync.`,
+      params: z.object({
+        syncId: z.string().uuid().describe(SecretSyncs.SYNC_SECRETS(destination).syncId)
+      }),
+      response: {
+        200: z.object({ secretSync: responseSchema })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const { syncId } = req.params;
+
+      const secretSync = (await server.services.secretSync.triggerSecretSyncSyncSecretsById(
+        {
+          syncId,
+          destination,
+          auditLogInfo: req.auditLogInfo
+        },
+        req.permission
+      )) as T;
+
+      return { secretSync };
+    }
+  });
+
+  server.route({
+    method: "POST",
+    url: "/:syncId/import-secrets",
+    config: {
+      rateLimit: writeLimit
+    },
+    schema: {
+      description: `Import secrets from the specified ${destinationName} Sync destination.`,
+      params: z.object({
+        syncId: z.string().uuid().describe(SecretSyncs.IMPORT_SECRETS(destination).syncId)
+      }),
+      querystring: z.object({
+        importBehavior: z
+          .nativeEnum(SecretSyncImportBehavior)
+          .describe(SecretSyncs.IMPORT_SECRETS(destination).importBehavior)
+      }),
+      response: {
+        200: z.object({ secretSync: responseSchema })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const { syncId } = req.params;
+      const { importBehavior } = req.query;
+
+      const secretSync = (await server.services.secretSync.triggerSecretSyncImportSecretsById(
+        {
+          syncId,
+          destination,
+          importBehavior
+        },
+        req.permission
+      )) as T;
+
+      return { secretSync };
+    }
+  });
+
+  server.route({
+    method: "POST",
+    url: "/:syncId/remove-secrets",
+    config: {
+      rateLimit: writeLimit
+    },
+    schema: {
+      description: `Remove previously synced secrets from the specified ${destinationName} Sync destination.`,
+      params: z.object({
+        syncId: z.string().uuid().describe(SecretSyncs.REMOVE_SECRETS(destination).syncId)
+      }),
+      response: {
+        200: z.object({ secretSync: responseSchema })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const { syncId } = req.params;
+
+      const secretSync = (await server.services.secretSync.triggerSecretSyncRemoveSecretsById(
+        {
+          syncId,
+          destination
+        },
+        req.permission
+      )) as T;
+
+      return { secretSync };
+    }
+  });
+};
diff --git a/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts b/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts
new file mode 100644
index 0000000000..5736767ddd
--- /dev/null
+++ b/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts
@@ -0,0 +1,82 @@
+import { z } from "zod";
+
+import { EventType } from "@app/ee/services/audit-log/audit-log-types";
+import { SecretSyncs } from "@app/lib/api-docs";
+import { readLimit } from "@app/server/config/rateLimiter";
+import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
+import { AuthMode } from "@app/services/auth/auth-type";
+import {
+  AwsParameterStoreSyncListItemSchema,
+  AwsParameterStoreSyncSchema
+} from "@app/services/secret-sync/aws-parameter-store";
+import { GitHubSyncListItemSchema, GitHubSyncSchema } from "@app/services/secret-sync/github";
+
+const SecretSyncSchema = z.discriminatedUnion("destination", [AwsParameterStoreSyncSchema, GitHubSyncSchema]);
+
+const SecretSyncOptionsSchema = z.discriminatedUnion("destination", [
+  AwsParameterStoreSyncListItemSchema,
+  GitHubSyncListItemSchema
+]);
+
+export const registerSecretSyncRouter = async (server: FastifyZodProvider) => {
+  server.route({
+    method: "GET",
+    url: "/options",
+    config: {
+      rateLimit: readLimit
+    },
+    schema: {
+      description: "List the available Secret Sync Options.",
+      response: {
+        200: z.object({
+          secretSyncOptions: SecretSyncOptionsSchema.array()
+        })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: () => {
+      const secretSyncOptions = server.services.secretSync.listSecretSyncOptions();
+      return { secretSyncOptions };
+    }
+  });
+
+  server.route({
+    method: "GET",
+    url: "/",
+    config: {
+      rateLimit: readLimit
+    },
+    schema: {
+      description: "List all the Secret Syncs for the specified project.",
+      querystring: z.object({
+        projectId: z.string().trim().min(1, "Project ID required").describe(SecretSyncs.LIST().projectId)
+      }),
+      response: {
+        200: z.object({ secretSyncs: SecretSyncSchema.array() })
+      }
+    },
+    onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+    handler: async (req) => {
+      const {
+        query: { projectId },
+        permission
+      } = req;
+
+      const secretSyncs = await server.services.secretSync.listSecretSyncsByProjectId({ projectId }, permission);
+
+      await server.services.auditLog.createAuditLog({
+        ...req.auditLogInfo,
+        projectId,
+        event: {
+          type: EventType.GET_SECRET_SYNCS,
+          metadata: {
+            syncIds: secretSyncs.map((sync) => sync.id),
+            count: secretSyncs.length
+          }
+        }
+      });
+
+      return { secretSyncs };
+    }
+  });
+};
diff --git a/backend/src/services/app-connection/app-connection-enums.ts b/backend/src/services/app-connection/app-connection-enums.ts
index d69b7dec1a..e96886e9f9 100644
--- a/backend/src/services/app-connection/app-connection-enums.ts
+++ b/backend/src/services/app-connection/app-connection-enums.ts
@@ -2,3 +2,50 @@ export enum AppConnection {
   GitHub = "github",
   AWS = "aws"
 }
+
+export enum AWSRegion {
+  // US
+  US_EAST_1 = "us-east-1", // N. Virginia
+  US_EAST_2 = "us-east-2", // Ohio
+  US_WEST_1 = "us-west-1", // N. California
+  US_WEST_2 = "us-west-2", // Oregon
+
+  // GovCloud
+  US_GOV_EAST_1 = "us-gov-east-1", // US-East
+  US_GOV_WEST_1 = "us-gov-west-1", // US-West
+
+  // Africa
+  AF_SOUTH_1 = "af-south-1", // Cape Town
+
+  // Asia Pacific
+  AP_EAST_1 = "ap-east-1", // Hong Kong
+  AP_SOUTH_1 = "ap-south-1", // Mumbai
+  AP_SOUTH_2 = "ap-south-2", // Hyderabad
+  AP_NORTHEAST_1 = "ap-northeast-1", // Tokyo
+  AP_NORTHEAST_2 = "ap-northeast-2", // Seoul
+  AP_NORTHEAST_3 = "ap-northeast-3", // Osaka
+  AP_SOUTHEAST_1 = "ap-southeast-1", // Singapore
+  AP_SOUTHEAST_2 = "ap-southeast-2", // Sydney
+  AP_SOUTHEAST_3 = "ap-southeast-3", // Jakarta
+  AP_SOUTHEAST_4 = "ap-southeast-4", // Melbourne
+
+  // Canada
+  CA_CENTRAL_1 = "ca-central-1", // Central
+
+  // Europe
+  EU_CENTRAL_1 = "eu-central-1", // Frankfurt
+  EU_CENTRAL_2 = "eu-central-2", // Zurich
+  EU_WEST_1 = "eu-west-1", // Ireland
+  EU_WEST_2 = "eu-west-2", // London
+  EU_WEST_3 = "eu-west-3", // Paris
+  EU_SOUTH_1 = "eu-south-1", // Milan
+  EU_SOUTH_2 = "eu-south-2", // Spain
+  EU_NORTH_1 = "eu-north-1", // Stockholm
+
+  // Middle East
+  ME_SOUTH_1 = "me-south-1", // Bahrain
+  ME_CENTRAL_1 = "me-central-1", // UAE
+
+  // South America
+  SA_EAST_1 = "sa-east-1" // Sao Paulo
+}
diff --git a/backend/src/services/app-connection/app-connection-fns.ts b/backend/src/services/app-connection/app-connection-fns.ts
index 787839cf7b..3f52b12854 100644
--- a/backend/src/services/app-connection/app-connection-fns.ts
+++ b/backend/src/services/app-connection/app-connection-fns.ts
@@ -1,3 +1,4 @@
+import { TAppConnections } from "@app/db/schemas/app-connections";
 import { AppConnection } from "@app/services/app-connection/app-connection-enums";
 import { TAppConnectionServiceFactoryDep } from "@app/services/app-connection/app-connection-service";
 import { TAppConnection, TAppConnectionConfig } from "@app/services/app-connection/app-connection-types";
@@ -64,9 +65,8 @@ export const validateAppConnectionCredentials = async (
 ): Promise<TAppConnection["credentials"]> => {
   const { app } = appConnection;
   switch (app) {
-    case AppConnection.AWS: {
+    case AppConnection.AWS:
       return validateAwsConnectionCredentials(appConnection);
-    }
     case AppConnection.GitHub:
       return validateGitHubConnectionCredentials(appConnection);
     default:
@@ -90,3 +90,17 @@ export const getAppConnectionMethodName = (method: TAppConnection["method"]) =>
       throw new Error(`Unhandled App Connection Method: ${method}`);
   }
 };
+
+export const decryptAppConnection = async (
+  appConnection: TAppConnections,
+  kmsService: TAppConnectionServiceFactoryDep["kmsService"]
+) => {
+  return {
+    ...appConnection,
+    credentials: await decryptAppConnectionCredentials({
+      encryptedCredentials: appConnection.encryptedCredentials,
+      orgId: appConnection.orgId,
+      kmsService
+    })
+  } as TAppConnection;
+};
diff --git a/backend/src/services/app-connection/app-connection-service.ts b/backend/src/services/app-connection/app-connection-service.ts
index 9b9f16626d..91e7d9dc44 100644
--- a/backend/src/services/app-connection/app-connection-service.ts
+++ b/backend/src/services/app-connection/app-connection-service.ts
@@ -1,13 +1,12 @@
-import { ForbiddenError } from "@casl/ability";
+import { ForbiddenError, subject } from "@casl/ability";
 
-import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
-import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
+import { OrgPermissionAppConnectionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
 import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
-import { BadRequestError, NotFoundError } from "@app/lib/errors";
+import { BadRequestError, DatabaseError, NotFoundError } from "@app/lib/errors";
 import { DiscriminativePick, OrgServiceActor } from "@app/lib/types";
 import { AppConnection } from "@app/services/app-connection/app-connection-enums";
 import {
-  decryptAppConnectionCredentials,
+  decryptAppConnection,
   encryptAppConnectionCredentials,
   getAppConnectionMethodName,
   listAppConnectionOptions,
@@ -23,6 +22,7 @@ import {
 } from "@app/services/app-connection/app-connection-types";
 import { ValidateAwsConnectionCredentialsSchema } from "@app/services/app-connection/aws";
 import { ValidateGitHubConnectionCredentialsSchema } from "@app/services/app-connection/github";
+import { githubConnectionService } from "@app/services/app-connection/github/github-connection-service";
 import { TKmsServiceFactory } from "@app/services/kms/kms-service";
 
 import { TAppConnectionDALFactory } from "./app-connection-dal";
@@ -31,7 +31,6 @@ export type TAppConnectionServiceFactoryDep = {
   appConnectionDAL: TAppConnectionDALFactory;
   permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
   kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
-  licenseService: Pick<TLicenseServiceFactory, "getPlan">; // TODO: remove once launched
 };
 
 export type TAppConnectionServiceFactory = ReturnType<typeof appConnectionServiceFactory>;
@@ -44,19 +43,9 @@ const VALIDATE_APP_CONNECTION_CREDENTIALS_MAP: Record<AppConnection, TValidateAp
 export const appConnectionServiceFactory = ({
   appConnectionDAL,
   permissionService,
-  kmsService,
-  licenseService
+  kmsService
 }: TAppConnectionServiceFactoryDep) => {
-  // app connections are disabled for public until launch
-  const checkAppServicesAvailability = async (orgId: string) => {
-    const subscription = await licenseService.getPlan(orgId);
-
-    if (!subscription.appConnections) throw new BadRequestError({ message: "App Connections are not available yet." });
-  };
-
   const listAppConnectionsByOrg = async (actor: OrgServiceActor, app?: AppConnection) => {
-    await checkAppServicesAvailability(actor.orgId);
-
     const { permission } = await permissionService.getOrgPermission(
       actor.type,
       actor.id,
@@ -65,7 +54,10 @@ export const appConnectionServiceFactory = ({
       actor.orgId
     );
 
-    ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.AppConnections);
+    ForbiddenError.from(permission).throwUnlessCan(
+      OrgPermissionAppConnectionActions.Read,
+      OrgPermissionSubjects.AppConnections
+    );
 
     const appConnections = await appConnectionDAL.find(
       app
@@ -78,24 +70,11 @@ export const appConnectionServiceFactory = ({
     return Promise.all(
       appConnections
         .sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()))
-        .map(async ({ encryptedCredentials, ...connection }) => {
-          const credentials = await decryptAppConnectionCredentials({
-            encryptedCredentials,
-            kmsService,
-            orgId: connection.orgId
-          });
-
-          return {
-            ...connection,
-            credentials
-          } as TAppConnection;
-        })
+        .map((appConnection) => decryptAppConnection(appConnection, kmsService))
     );
   };
 
   const findAppConnectionById = async (app: AppConnection, connectionId: string, actor: OrgServiceActor) => {
-    await checkAppServicesAvailability(actor.orgId);
-
     const appConnection = await appConnectionDAL.findById(connectionId);
 
     if (!appConnection) throw new NotFoundError({ message: `Could not find App Connection with ID ${connectionId}` });
@@ -108,24 +87,18 @@ export const appConnectionServiceFactory = ({
       appConnection.orgId
     );
 
-    ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.AppConnections);
+    ForbiddenError.from(permission).throwUnlessCan(
+      OrgPermissionAppConnectionActions.Read,
+      OrgPermissionSubjects.AppConnections
+    );
 
     if (appConnection.app !== app)
       throw new BadRequestError({ message: `App Connection with ID ${connectionId} is not for App "${app}"` });
 
-    return {
-      ...appConnection,
-      credentials: await decryptAppConnectionCredentials({
-        encryptedCredentials: appConnection.encryptedCredentials,
-        orgId: appConnection.orgId,
-        kmsService
-      })
-    } as TAppConnection;
+    return decryptAppConnection(appConnection, kmsService);
   };
 
   const findAppConnectionByName = async (app: AppConnection, connectionName: string, actor: OrgServiceActor) => {
-    await checkAppServicesAvailability(actor.orgId);
-
     const appConnection = await appConnectionDAL.findOne({ name: connectionName, orgId: actor.orgId });
 
     if (!appConnection)
@@ -139,27 +112,21 @@ export const appConnectionServiceFactory = ({
       appConnection.orgId
     );
 
-    ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.AppConnections);
+    ForbiddenError.from(permission).throwUnlessCan(
+      OrgPermissionAppConnectionActions.Read,
+      OrgPermissionSubjects.AppConnections
+    );
 
     if (appConnection.app !== app)
       throw new BadRequestError({ message: `App Connection with name ${connectionName} is not for App "${app}"` });
 
-    return {
-      ...appConnection,
-      credentials: await decryptAppConnectionCredentials({
-        encryptedCredentials: appConnection.encryptedCredentials,
-        orgId: appConnection.orgId,
-        kmsService
-      })
-    } as TAppConnection;
+    return decryptAppConnection(appConnection, kmsService);
   };
 
   const createAppConnection = async (
     { method, app, credentials, ...params }: TCreateAppConnectionDTO,
     actor: OrgServiceActor
   ) => {
-    await checkAppServicesAvailability(actor.orgId);
-
     const { permission } = await permissionService.getOrgPermission(
       actor.type,
       actor.id,
@@ -168,7 +135,10 @@ export const appConnectionServiceFactory = ({
       actor.orgId
     );
 
-    ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.AppConnections);
+    ForbiddenError.from(permission).throwUnlessCan(
+      OrgPermissionAppConnectionActions.Create,
+      OrgPermissionSubjects.AppConnections
+    );
 
     const appConnection = await appConnectionDAL.transaction(async (tx) => {
       const isConflictingName = Boolean(
@@ -216,15 +186,13 @@ export const appConnectionServiceFactory = ({
       };
     });
 
-    return appConnection;
+    return appConnection as TAppConnection;
   };
 
   const updateAppConnection = async (
     { connectionId, credentials, ...params }: TUpdateAppConnectionDTO,
     actor: OrgServiceActor
   ) => {
-    await checkAppServicesAvailability(actor.orgId);
-
     const appConnection = await appConnectionDAL.findById(connectionId);
 
     if (!appConnection) throw new NotFoundError({ message: `Could not find App Connection with ID ${connectionId}` });
@@ -237,7 +205,10 @@ export const appConnectionServiceFactory = ({
       appConnection.orgId
     );
 
-    ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.AppConnections);
+    ForbiddenError.from(permission).throwUnlessCan(
+      OrgPermissionAppConnectionActions.Edit,
+      OrgPermissionSubjects.AppConnections
+    );
 
     const updatedAppConnection = await appConnectionDAL.transaction(async (tx) => {
       if (params.name && appConnection.name !== params.name) {
@@ -304,19 +275,10 @@ export const appConnectionServiceFactory = ({
       return updatedConnection;
     });
 
-    return {
-      ...updatedAppConnection,
-      credentials: await decryptAppConnectionCredentials({
-        encryptedCredentials: updatedAppConnection.encryptedCredentials,
-        orgId: updatedAppConnection.orgId,
-        kmsService
-      })
-    } as TAppConnection;
+    return decryptAppConnection(updatedAppConnection, kmsService);
   };
 
   const deleteAppConnection = async (app: AppConnection, connectionId: string, actor: OrgServiceActor) => {
-    await checkAppServicesAvailability(actor.orgId);
-
     const appConnection = await appConnectionDAL.findById(connectionId);
 
     if (!appConnection) throw new NotFoundError({ message: `Could not find App Connection with ID ${connectionId}` });
@@ -329,23 +291,85 @@ export const appConnectionServiceFactory = ({
       appConnection.orgId
     );
 
-    ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.AppConnections);
+    ForbiddenError.from(permission).throwUnlessCan(
+      OrgPermissionAppConnectionActions.Delete,
+      OrgPermissionSubjects.AppConnections
+    );
 
     if (appConnection.app !== app)
       throw new BadRequestError({ message: `App Connection with ID ${connectionId} is not for App "${app}"` });
 
-    // TODO: specify delete error message if due to existing dependencies
+    // TODO (scott): add option to delete all dependencies
 
-    const deletedAppConnection = await appConnectionDAL.deleteById(connectionId);
+    try {
+      const deletedAppConnection = await appConnectionDAL.deleteById(connectionId);
 
-    return {
-      ...deletedAppConnection,
-      credentials: await decryptAppConnectionCredentials({
-        encryptedCredentials: deletedAppConnection.encryptedCredentials,
-        orgId: deletedAppConnection.orgId,
-        kmsService
-      })
-    } as TAppConnection;
+      return await decryptAppConnection(deletedAppConnection, kmsService);
+    } catch (err) {
+      if (err instanceof DatabaseError && (err.error as { code: string })?.code === "23503") {
+        throw new BadRequestError({
+          message:
+            "Cannot delete App Connection with existing connections. Remove all existing connections and try again."
+        });
+      }
+
+      throw err;
+    }
+  };
+
+  const connectAppConnectionById = async <T extends TAppConnection>(
+    app: AppConnection,
+    connectionId: string,
+    actor: OrgServiceActor
+  ) => {
+    const appConnection = await appConnectionDAL.findById(connectionId);
+
+    if (!appConnection) throw new NotFoundError({ message: `Could not find App Connection with ID ${connectionId}` });
+
+    const { permission: orgPermission } = await permissionService.getOrgPermission(
+      actor.type,
+      actor.id,
+      appConnection.orgId,
+      actor.authMethod,
+      actor.orgId
+    );
+
+    ForbiddenError.from(orgPermission).throwUnlessCan(
+      OrgPermissionAppConnectionActions.Connect,
+      subject(OrgPermissionSubjects.AppConnections, { connectionId: appConnection.id })
+    );
+
+    if (appConnection.app !== app)
+      throw new BadRequestError({
+        message: `${
+          APP_CONNECTION_NAME_MAP[appConnection.app as AppConnection]
+        } Connection with ID ${connectionId} cannot be used to connect to ${APP_CONNECTION_NAME_MAP[app]}`
+      });
+
+    const connection = await decryptAppConnection(appConnection, kmsService);
+
+    return connection as T;
+  };
+
+  const listAvailableAppConnectionsForUser = async (app: AppConnection, actor: OrgServiceActor) => {
+    const { permission: orgPermission } = await permissionService.getOrgPermission(
+      actor.type,
+      actor.id,
+      actor.orgId,
+      actor.authMethod,
+      actor.orgId
+    );
+
+    const appConnections = await appConnectionDAL.find({ app, orgId: actor.orgId });
+
+    const availableConnections = appConnections.filter((connection) =>
+      orgPermission.can(
+        OrgPermissionAppConnectionActions.Connect,
+        subject(OrgPermissionSubjects.AppConnections, { connectionId: connection.id })
+      )
+    );
+
+    return availableConnections as Omit<TAppConnection, "credentials">[];
   };
 
   return {
@@ -355,6 +379,9 @@ export const appConnectionServiceFactory = ({
     findAppConnectionByName,
     createAppConnection,
     updateAppConnection,
-    deleteAppConnection
+    deleteAppConnection,
+    connectAppConnectionById,
+    listAvailableAppConnectionsForUser,
+    github: githubConnectionService(connectAppConnectionById)
   };
 };
diff --git a/backend/src/services/app-connection/aws/aws-connection-fns.ts b/backend/src/services/app-connection/aws/aws-connection-fns.ts
index 36008bc58a..d814215298 100644
--- a/backend/src/services/app-connection/aws/aws-connection-fns.ts
+++ b/backend/src/services/app-connection/aws/aws-connection-fns.ts
@@ -4,7 +4,7 @@ import { randomUUID } from "crypto";
 
 import { getConfig } from "@app/lib/config/env";
 import { BadRequestError, InternalServerError } from "@app/lib/errors";
-import { AppConnection } from "@app/services/app-connection/app-connection-enums";
+import { AppConnection, AWSRegion } from "@app/services/app-connection/app-connection-enums";
 
 import { AwsConnectionMethod } from "./aws-connection-enums";
 import { TAwsConnectionConfig } from "./aws-connection-types";
@@ -20,7 +20,7 @@ export const getAwsAppConnectionListItem = () => {
   };
 };
 
-export const getAwsConnectionConfig = async (appConnection: TAwsConnectionConfig, region = "us-east-1") => {
+export const getAwsConnectionConfig = async (appConnection: TAwsConnectionConfig, region = AWSRegion.US_EAST_1) => {
   const appCfg = getConfig();
 
   let accessKeyId: string;
diff --git a/backend/src/services/app-connection/aws/aws-connection-schemas.ts b/backend/src/services/app-connection/aws/aws-connection-schemas.ts
index 914e92671f..c06c6f0edb 100644
--- a/backend/src/services/app-connection/aws/aws-connection-schemas.ts
+++ b/backend/src/services/app-connection/aws/aws-connection-schemas.ts
@@ -38,11 +38,11 @@ export const AwsConnectionSchema = z.intersection(
 export const SanitizedAwsConnectionSchema = z.discriminatedUnion("method", [
   BaseAwsConnectionSchema.extend({
     method: z.literal(AwsConnectionMethod.AssumeRole),
-    credentials: AwsConnectionAssumeRoleCredentialsSchema.omit({ roleArn: true })
+    credentials: AwsConnectionAssumeRoleCredentialsSchema.pick({})
   }),
   BaseAwsConnectionSchema.extend({
     method: z.literal(AwsConnectionMethod.AccessKey),
-    credentials: AwsConnectionAccessTokenCredentialsSchema.omit({ secretAccessKey: true })
+    credentials: AwsConnectionAccessTokenCredentialsSchema.pick({ accessKeyId: true })
   })
 ]);
 
@@ -75,7 +75,7 @@ export const UpdateAwsConnectionSchema = z
 export const AwsConnectionListItemSchema = z.object({
   name: z.literal("AWS"),
   app: z.literal(AppConnection.AWS),
-  // the below is preferable but currently breaks mintlify
+  // the below is preferable but currently breaks with our zod to json schema parser
   // methods: z.tuple([z.literal(AwsConnectionMethod.AssumeRole), z.literal(AwsConnectionMethod.AccessKey)]),
   methods: z.nativeEnum(AwsConnectionMethod).array(),
   accessKeyId: z.string().optional()
diff --git a/backend/src/services/app-connection/github/github-connection-fns.ts b/backend/src/services/app-connection/github/github-connection-fns.ts
index 01fa7846fb..391ba5f965 100644
--- a/backend/src/services/app-connection/github/github-connection-fns.ts
+++ b/backend/src/services/app-connection/github/github-connection-fns.ts
@@ -1,3 +1,5 @@
+import { createAppAuth } from "@octokit/auth-app";
+import { Octokit } from "@octokit/rest";
 import { AxiosResponse } from "axios";
 
 import { getConfig } from "@app/lib/config/env";
@@ -8,7 +10,7 @@ import { IntegrationUrls } from "@app/services/integration-auth/integration-list
 
 import { AppConnection } from "../app-connection-enums";
 import { GitHubConnectionMethod } from "./github-connection-enums";
-import { TGitHubConnectionConfig } from "./github-connection-types";
+import { TGitHubConnection, TGitHubConnectionConfig } from "./github-connection-types";
 
 export const getGitHubConnectionListItem = () => {
   const { INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID, INF_APP_CONNECTION_GITHUB_APP_SLUG } = getConfig();
@@ -22,10 +24,131 @@ export const getGitHubConnectionListItem = () => {
   };
 };
 
+export const getGitHubClient = (appConnection: TGitHubConnection) => {
+  const appCfg = getConfig();
+
+  const { method, credentials } = appConnection;
+
+  let client: Octokit;
+
+  switch (method) {
+    case GitHubConnectionMethod.App:
+      if (!appCfg.INF_APP_CONNECTION_GITHUB_APP_ID || !appCfg.INF_APP_CONNECTION_GITHUB_APP_PRIVATE_KEY) {
+        throw new InternalServerError({
+          message: `GitHub ${getAppConnectionMethodName(method).replace(
+            "GitHub",
+            ""
+          )} environment variables have not been configured`
+        });
+      }
+
+      client = new Octokit({
+        authStrategy: createAppAuth,
+        auth: {
+          appId: appCfg.INF_APP_CONNECTION_GITHUB_APP_ID,
+          privateKey: appCfg.INF_APP_CONNECTION_GITHUB_APP_PRIVATE_KEY,
+          installationId: credentials.installationId
+        }
+      });
+      break;
+    case GitHubConnectionMethod.OAuth:
+      client = new Octokit({
+        auth: credentials.accessToken
+      });
+      break;
+    default:
+      throw new InternalServerError({
+        message: `Unhandled GitHub connection method: ${method as GitHubConnectionMethod}`
+      });
+  }
+
+  return client;
+};
+
+type GitHubOrganization = {
+  login: string;
+  id: number;
+};
+
+type GitHubRepository = {
+  id: number;
+  name: string;
+  owner: GitHubOrganization;
+};
+
+export const getGitHubRepositories = async (appConnection: TGitHubConnection) => {
+  const client = getGitHubClient(appConnection);
+
+  let repositories: GitHubRepository[];
+
+  switch (appConnection.method) {
+    case GitHubConnectionMethod.App:
+      repositories = await client.paginate("GET /installation/repositories");
+      break;
+    case GitHubConnectionMethod.OAuth:
+    default:
+      repositories = (await client.paginate("GET /user/repos")).filter((repo) => repo.permissions?.admin);
+      break;
+  }
+
+  return repositories;
+};
+
+export const getGitHubOrganizations = async (appConnection: TGitHubConnection) => {
+  const client = getGitHubClient(appConnection);
+
+  let organizations: GitHubOrganization[];
+
+  switch (appConnection.method) {
+    case GitHubConnectionMethod.App: {
+      const installationRepositories = await client.paginate("GET /installation/repositories");
+
+      const organizationMap: Record<string, GitHubOrganization> = {};
+
+      installationRepositories.forEach((repo) => {
+        if (repo.owner.type === "Organization") {
+          organizationMap[repo.owner.id] = repo.owner;
+        }
+      });
+
+      organizations = Object.values(organizationMap);
+
+      break;
+    }
+    case GitHubConnectionMethod.OAuth:
+    default:
+      organizations = await client.paginate("GET /user/orgs");
+      break;
+  }
+
+  return organizations;
+};
+
+export const getGitHubEnvironments = async (appConnection: TGitHubConnection, owner: string, repo: string) => {
+  const client = getGitHubClient(appConnection);
+
+  try {
+    const environments = await client.paginate("GET /repos/{owner}/{repo}/environments", {
+      owner,
+      repo
+    });
+
+    return environments;
+  } catch (e) {
+    // repo doesn't have envs
+    if ((e as { status: number }).status === 404) {
+      return [];
+    }
+
+    throw e;
+  }
+};
+
 type TokenRespData = {
   access_token: string;
   scope: string;
   token_type: string;
+  error?: string;
 };
 
 export const validateGitHubConnectionCredentials = async (config: TGitHubConnectionConfig) => {
@@ -53,7 +176,10 @@ export const validateGitHubConnectionCredentials = async (config: TGitHubConnect
 
   if (!clientId || !clientSecret) {
     throw new InternalServerError({
-      message: `GitHub ${getAppConnectionMethodName(method)} environment variables have not been configured`
+      message: `GitHub ${getAppConnectionMethodName(method).replace(
+        "GitHub",
+        ""
+      )} environment variables have not been configured`
     });
   }
 
@@ -65,7 +191,7 @@ export const validateGitHubConnectionCredentials = async (config: TGitHubConnect
         client_id: clientId,
         client_secret: clientSecret,
         code: credentials.code,
-        redirect_uri: `${SITE_URL}/app-connections/github/oauth/callback`
+        redirect_uri: `${SITE_URL}/organization/app-connections/github/oauth/callback`
       },
       headers: {
         Accept: "application/json",
@@ -90,6 +216,8 @@ export const validateGitHubConnectionCredentials = async (config: TGitHubConnect
         id: number;
         account: {
           login: string;
+          type: string;
+          id: number;
         };
       }[];
     }>(IntegrationUrls.GITHUB_USER_INSTALLATIONS, {
@@ -111,10 +239,13 @@ export const validateGitHubConnectionCredentials = async (config: TGitHubConnect
     }
   }
 
+  if (!tokenResp.data.access_token) {
+    throw new InternalServerError({ message: `Missing access token: ${tokenResp.data.error}` });
+  }
+
   switch (method) {
     case GitHubConnectionMethod.App:
       return {
-        // access token not needed for GitHub App
         installationId: credentials.installationId
       };
     case GitHubConnectionMethod.OAuth:
diff --git a/backend/src/services/app-connection/github/github-connection-schemas.ts b/backend/src/services/app-connection/github/github-connection-schemas.ts
index 5adb211bac..e98b9169db 100644
--- a/backend/src/services/app-connection/github/github-connection-schemas.ts
+++ b/backend/src/services/app-connection/github/github-connection-schemas.ts
@@ -57,7 +57,7 @@ export const UpdateGitHubConnectionSchema = z
 
 const BaseGitHubConnectionSchema = BaseAppConnectionSchema.extend({ app: z.literal(AppConnection.GitHub) });
 
-export const GitHubAppConnectionSchema = z.intersection(
+export const GitHubConnectionSchema = z.intersection(
   BaseGitHubConnectionSchema,
   z.discriminatedUnion("method", [
     z.object({
@@ -74,19 +74,19 @@ export const GitHubAppConnectionSchema = z.intersection(
 export const SanitizedGitHubConnectionSchema = z.discriminatedUnion("method", [
   BaseGitHubConnectionSchema.extend({
     method: z.literal(GitHubConnectionMethod.App),
-    credentials: GitHubConnectionAppOutputCredentialsSchema.omit({ installationId: true })
+    credentials: GitHubConnectionAppOutputCredentialsSchema.pick({})
   }),
   BaseGitHubConnectionSchema.extend({
     method: z.literal(GitHubConnectionMethod.OAuth),
-    credentials: GitHubConnectionOAuthOutputCredentialsSchema.omit({ accessToken: true })
+    credentials: GitHubConnectionOAuthOutputCredentialsSchema.pick({})
   })
 ]);
 
 export const GitHubConnectionListItemSchema = z.object({
   name: z.literal("GitHub"),
   app: z.literal(AppConnection.GitHub),
-  // the below is preferable but currently breaks mintlify
-  // methods: z.tuple([z.literal(GitHubConnectionMethod.GitHubApp), z.literal(GitHubConnectionMethod.OAuth)]),
+  // the below is preferable but currently breaks with our zod to json schema parser
+  // methods: z.tuple([z.literal(GitHubConnectionMethod.App), z.literal(GitHubConnectionMethod.OAuth)]),
   methods: z.nativeEnum(GitHubConnectionMethod).array(),
   oauthClientId: z.string().optional(),
   appClientSlug: z.string().optional()
diff --git a/backend/src/services/app-connection/github/github-connection-service.ts b/backend/src/services/app-connection/github/github-connection-service.ts
new file mode 100644
index 0000000000..b4e95c5a7f
--- /dev/null
+++ b/backend/src/services/app-connection/github/github-connection-service.ts
@@ -0,0 +1,55 @@
+import { OrgServiceActor } from "@app/lib/types";
+import { AppConnection } from "@app/services/app-connection/app-connection-enums";
+import {
+  getGitHubEnvironments,
+  getGitHubOrganizations,
+  getGitHubRepositories
+} from "@app/services/app-connection/github/github-connection-fns";
+import { TGitHubConnection } from "@app/services/app-connection/github/github-connection-types";
+
+type TGetAppConnectionFunc = (
+  app: AppConnection,
+  connectionId: string,
+  actor: OrgServiceActor
+) => Promise<TGitHubConnection>;
+
+type TListGitHubEnvironmentsDTO = {
+  connectionId: string;
+  repo: string;
+  owner: string;
+};
+
+export const githubConnectionService = (getAppConnection: TGetAppConnectionFunc) => {
+  const listRepositories = async (connectionId: string, actor: OrgServiceActor) => {
+    const appConnection = await getAppConnection(AppConnection.GitHub, connectionId, actor);
+
+    const repositories = await getGitHubRepositories(appConnection);
+
+    return repositories;
+  };
+
+  const listOrganizations = async (connectionId: string, actor: OrgServiceActor) => {
+    const appConnection = await getAppConnection(AppConnection.GitHub, connectionId, actor);
+
+    const organizations = await getGitHubOrganizations(appConnection);
+
+    return organizations;
+  };
+
+  const listEnvironments = async (
+    { connectionId, repo, owner }: TListGitHubEnvironmentsDTO,
+    actor: OrgServiceActor
+  ) => {
+    const appConnection = await getAppConnection(AppConnection.GitHub, connectionId, actor);
+
+    const environments = await getGitHubEnvironments(appConnection, owner, repo);
+
+    return environments;
+  };
+
+  return {
+    listRepositories,
+    listOrganizations,
+    listEnvironments
+  };
+};
diff --git a/backend/src/services/app-connection/github/github-connection-types.ts b/backend/src/services/app-connection/github/github-connection-types.ts
index 5a9b13c00f..714c871749 100644
--- a/backend/src/services/app-connection/github/github-connection-types.ts
+++ b/backend/src/services/app-connection/github/github-connection-types.ts
@@ -5,11 +5,11 @@ import { DiscriminativePick } from "@app/lib/types";
 import { AppConnection } from "../app-connection-enums";
 import {
   CreateGitHubConnectionSchema,
-  GitHubAppConnectionSchema,
+  GitHubConnectionSchema,
   ValidateGitHubConnectionCredentialsSchema
 } from "./github-connection-schemas";
 
-export type TGitHubConnection = z.infer<typeof GitHubAppConnectionSchema>;
+export type TGitHubConnection = z.infer<typeof GitHubConnectionSchema>;
 
 export type TGitHubConnectionInput = z.infer<typeof CreateGitHubConnectionSchema> & {
   app: AppConnection.GitHub;
diff --git a/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-constants.ts b/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-constants.ts
new file mode 100644
index 0000000000..37605442d1
--- /dev/null
+++ b/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-constants.ts
@@ -0,0 +1,10 @@
+import { AppConnection } from "@app/services/app-connection/app-connection-enums";
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+import { TSecretSyncListItem } from "@app/services/secret-sync/secret-sync-types";
+
+export const AWS_PARAMETER_STORE_SYNC_LIST_OPTION: TSecretSyncListItem = {
+  name: "AWS Parameter Store",
+  destination: SecretSync.AWSParameterStore,
+  connection: AppConnection.AWS,
+  canImportSecrets: true
+};
diff --git a/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-fns.ts b/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-fns.ts
new file mode 100644
index 0000000000..a495f9e839
--- /dev/null
+++ b/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-fns.ts
@@ -0,0 +1,207 @@
+import AWS, { AWSError } from "aws-sdk";
+
+import { getAwsConnectionConfig } from "@app/services/app-connection/aws/aws-connection-fns";
+import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors";
+import { TSecretMap } from "@app/services/secret-sync/secret-sync-types";
+
+import { TAwsParameterStoreSyncWithCredentials } from "./aws-parameter-store-sync-types";
+
+type TAWSParameterStoreRecord = Record<string, AWS.SSM.Parameter>;
+
+const MAX_RETRIES = 5;
+const BATCH_SIZE = 10;
+
+const getSSM = async (secretSync: TAwsParameterStoreSyncWithCredentials) => {
+  const { destinationConfig, connection } = secretSync;
+
+  const config = await getAwsConnectionConfig(connection, destinationConfig.region);
+
+  const ssm = new AWS.SSM({
+    apiVersion: "2014-11-06",
+    region: destinationConfig.region
+  });
+
+  ssm.config.update(config);
+
+  return ssm;
+};
+
+const sleep = async () =>
+  new Promise((resolve) => {
+    setTimeout(resolve, 1000);
+  });
+
+const getParametersByPath = async (ssm: AWS.SSM, path: string): Promise<TAWSParameterStoreRecord> => {
+  const awsParameterStoreSecretsRecord: TAWSParameterStoreRecord = {};
+  let hasNext = true;
+  let nextToken: string | undefined;
+  let attempt = 0;
+
+  while (hasNext) {
+    try {
+      // eslint-disable-next-line no-await-in-loop
+      const parameters = await ssm
+        .getParametersByPath({
+          Path: path,
+          Recursive: false,
+          WithDecryption: true,
+          MaxResults: BATCH_SIZE,
+          NextToken: nextToken
+        })
+        .promise();
+
+      attempt = 0;
+
+      if (parameters.Parameters) {
+        parameters.Parameters.forEach((parameter) => {
+          if (parameter.Name) {
+            // no leading slash if path is '/'
+            const secKey = path.length > 1 ? parameter.Name.substring(path.length) : parameter.Name;
+            awsParameterStoreSecretsRecord[secKey] = parameter;
+          }
+        });
+      }
+
+      hasNext = Boolean(parameters.NextToken);
+      nextToken = parameters.NextToken;
+    } catch (e) {
+      if ((e as AWSError).code === "ThrottlingException" && attempt < MAX_RETRIES) {
+        attempt += 1;
+        // eslint-disable-next-line no-await-in-loop
+        await sleep();
+      }
+
+      throw e;
+    }
+  }
+
+  return awsParameterStoreSecretsRecord;
+};
+
+const putParameter = async (
+  ssm: AWS.SSM,
+  params: AWS.SSM.PutParameterRequest,
+  attempt = 0
+): Promise<AWS.SSM.PutParameterResult> => {
+  try {
+    return await ssm.putParameter(params).promise();
+  } catch (error) {
+    if ((error as AWSError).code === "ThrottlingException" && attempt < MAX_RETRIES) {
+      await sleep();
+
+      // retry
+      return putParameter(ssm, params, attempt + 1);
+    }
+    throw error;
+  }
+};
+
+const deleteParametersBatch = async (
+  ssm: AWS.SSM,
+  parameters: AWS.SSM.Parameter[],
+  attempt = 0
+): Promise<AWS.SSM.DeleteParameterResult[]> => {
+  const results: AWS.SSM.DeleteParameterResult[] = [];
+  let remainingParams = [...parameters];
+
+  while (remainingParams.length > 0) {
+    const batch = remainingParams.slice(0, BATCH_SIZE);
+
+    try {
+      // eslint-disable-next-line no-await-in-loop
+      const result = await ssm.deleteParameters({ Names: batch.map((param) => param.Name!) }).promise();
+      results.push(result);
+      remainingParams = remainingParams.slice(BATCH_SIZE);
+    } catch (error) {
+      if ((error as AWSError).code === "ThrottlingException" && attempt < MAX_RETRIES) {
+        // eslint-disable-next-line no-await-in-loop
+        await sleep();
+
+        // Retry the current batch
+        // eslint-disable-next-line no-await-in-loop
+        return [...results, ...(await deleteParametersBatch(ssm, remainingParams, attempt + 1))];
+      }
+      throw error;
+    }
+  }
+
+  return results;
+};
+
+export const AwsParameterStoreSyncFns = {
+  syncSecrets: async (secretSync: TAwsParameterStoreSyncWithCredentials, secretMap: TSecretMap) => {
+    const { destinationConfig } = secretSync;
+
+    const ssm = await getSSM(secretSync);
+
+    // TODO(scott): KMS Key ID, Tags
+
+    const awsParameterStoreSecretsRecord = await getParametersByPath(ssm, destinationConfig.path);
+
+    for await (const entry of Object.entries(secretMap)) {
+      const [key, { value }] = entry;
+
+      // skip empty values (not allowed by AWS) or secrets that haven't changed
+      if (!value || (key in awsParameterStoreSecretsRecord && awsParameterStoreSecretsRecord[key].Value === value)) {
+        // eslint-disable-next-line no-continue
+        continue;
+      }
+
+      try {
+        await putParameter(ssm, {
+          Name: `${destinationConfig.path}${key}`,
+          Type: "SecureString",
+          Value: value,
+          Overwrite: true
+        });
+      } catch (error) {
+        throw new SecretSyncError({
+          error,
+          secretKey: key
+        });
+      }
+    }
+
+    const parametersToDelete: AWS.SSM.Parameter[] = [];
+
+    for (const entry of Object.entries(awsParameterStoreSecretsRecord)) {
+      const [key, parameter] = entry;
+
+      if (!(key in secretMap) || !secretMap[key].value) {
+        parametersToDelete.push(parameter);
+      }
+    }
+
+    await deleteParametersBatch(ssm, parametersToDelete);
+  },
+  getSecrets: async (secretSync: TAwsParameterStoreSyncWithCredentials): Promise<TSecretMap> => {
+    const { destinationConfig } = secretSync;
+
+    const ssm = await getSSM(secretSync);
+
+    const awsParameterStoreSecretsRecord = await getParametersByPath(ssm, destinationConfig.path);
+
+    return Object.fromEntries(
+      Object.entries(awsParameterStoreSecretsRecord).map(([key, value]) => [key, { value: value.Value ?? "" }])
+    );
+  },
+  removeSecrets: async (secretSync: TAwsParameterStoreSyncWithCredentials, secretMap: TSecretMap) => {
+    const { destinationConfig } = secretSync;
+
+    const ssm = await getSSM(secretSync);
+
+    const awsParameterStoreSecretsRecord = await getParametersByPath(ssm, destinationConfig.path);
+
+    const parametersToDelete: AWS.SSM.Parameter[] = [];
+
+    for (const entry of Object.entries(awsParameterStoreSecretsRecord)) {
+      const [key, param] = entry;
+
+      if (key in secretMap) {
+        parametersToDelete.push(param);
+      }
+    }
+
+    await deleteParametersBatch(ssm, parametersToDelete);
+  }
+};
diff --git a/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-schemas.ts b/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-schemas.ts
new file mode 100644
index 0000000000..e89096baa1
--- /dev/null
+++ b/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-schemas.ts
@@ -0,0 +1,45 @@
+import { z } from "zod";
+
+import { SecretSyncs } from "@app/lib/api-docs";
+import { AppConnection, AWSRegion } from "@app/services/app-connection/app-connection-enums";
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+import {
+  BaseSecretSyncSchema,
+  GenericCreateSecretSyncFieldsSchema,
+  GenericUpdateSecretSyncFieldsSchema
+} from "@app/services/secret-sync/secret-sync-schemas";
+
+const AwsParameterStoreSyncDestinationConfigSchema = z.object({
+  region: z.nativeEnum(AWSRegion).describe(SecretSyncs.DESTINATION_CONFIG.AWS_PARAMETER_STORE.REGION),
+  path: z
+    .string()
+    .trim()
+    .min(1, "Parameter Store Path required")
+    .max(2048, "Cannot exceed 2048 characters")
+    .regex(/^\/([/]|(([\w-]+\/)+))?$/, 'Invalid path - must follow "/example/path/" format')
+    .describe(SecretSyncs.DESTINATION_CONFIG.AWS_PARAMETER_STORE.PATH)
+});
+
+export const AwsParameterStoreSyncSchema = BaseSecretSyncSchema(SecretSync.AWSParameterStore).extend({
+  destination: z.literal(SecretSync.AWSParameterStore),
+  destinationConfig: AwsParameterStoreSyncDestinationConfigSchema
+});
+
+export const CreateAwsParameterStoreSyncSchema = GenericCreateSecretSyncFieldsSchema(
+  SecretSync.AWSParameterStore
+).extend({
+  destinationConfig: AwsParameterStoreSyncDestinationConfigSchema
+});
+
+export const UpdateAwsParameterStoreSyncSchema = GenericUpdateSecretSyncFieldsSchema(
+  SecretSync.AWSParameterStore
+).extend({
+  destinationConfig: AwsParameterStoreSyncDestinationConfigSchema.optional()
+});
+
+export const AwsParameterStoreSyncListItemSchema = z.object({
+  name: z.literal("AWS Parameter Store"),
+  connection: z.literal(AppConnection.AWS),
+  destination: z.literal(SecretSync.AWSParameterStore),
+  canImportSecrets: z.literal(true)
+});
diff --git a/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-types.ts b/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-types.ts
new file mode 100644
index 0000000000..dada28435b
--- /dev/null
+++ b/backend/src/services/secret-sync/aws-parameter-store/aws-parameter-store-sync-types.ts
@@ -0,0 +1,19 @@
+import { z } from "zod";
+
+import { TAwsConnection } from "@app/services/app-connection/aws";
+
+import {
+  AwsParameterStoreSyncListItemSchema,
+  AwsParameterStoreSyncSchema,
+  CreateAwsParameterStoreSyncSchema
+} from "./aws-parameter-store-sync-schemas";
+
+export type TAwsParameterStoreSync = z.infer<typeof AwsParameterStoreSyncSchema>;
+
+export type TAwsParameterStoreSyncInput = z.infer<typeof CreateAwsParameterStoreSyncSchema>;
+
+export type TAwsParameterStoreSyncListItem = z.infer<typeof AwsParameterStoreSyncListItemSchema>;
+
+export type TAwsParameterStoreSyncWithCredentials = TAwsParameterStoreSync & {
+  connection: TAwsConnection;
+};
diff --git a/backend/src/services/secret-sync/aws-parameter-store/index.ts b/backend/src/services/secret-sync/aws-parameter-store/index.ts
new file mode 100644
index 0000000000..20728cd8ff
--- /dev/null
+++ b/backend/src/services/secret-sync/aws-parameter-store/index.ts
@@ -0,0 +1,4 @@
+export * from "./aws-parameter-store-sync-constants";
+export * from "./aws-parameter-store-sync-fns";
+export * from "./aws-parameter-store-sync-schemas";
+export * from "./aws-parameter-store-sync-types";
diff --git a/backend/src/services/secret-sync/github/github-sync-constants.ts b/backend/src/services/secret-sync/github/github-sync-constants.ts
new file mode 100644
index 0000000000..f97b96d9ee
--- /dev/null
+++ b/backend/src/services/secret-sync/github/github-sync-constants.ts
@@ -0,0 +1,10 @@
+import { AppConnection } from "@app/services/app-connection/app-connection-enums";
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+import { TSecretSyncListItem } from "@app/services/secret-sync/secret-sync-types";
+
+export const GITHUB_SYNC_LIST_OPTION: TSecretSyncListItem = {
+  name: "GitHub",
+  destination: SecretSync.GitHub,
+  connection: AppConnection.GitHub,
+  canImportSecrets: false
+};
diff --git a/backend/src/services/secret-sync/github/github-sync-enums.ts b/backend/src/services/secret-sync/github/github-sync-enums.ts
new file mode 100644
index 0000000000..c0109370ed
--- /dev/null
+++ b/backend/src/services/secret-sync/github/github-sync-enums.ts
@@ -0,0 +1,11 @@
+export enum GitHubSyncScope {
+  Repository = "repository",
+  Organization = "organization",
+  RepositoryEnvironment = "repository-environment"
+}
+
+export enum GitHubSyncVisibility {
+  All = "all",
+  Private = "private",
+  Selected = "selected"
+}
diff --git a/backend/src/services/secret-sync/github/github-sync-fns.ts b/backend/src/services/secret-sync/github/github-sync-fns.ts
new file mode 100644
index 0000000000..a09a411635
--- /dev/null
+++ b/backend/src/services/secret-sync/github/github-sync-fns.ts
@@ -0,0 +1,242 @@
+import { Octokit } from "@octokit/rest";
+import sodium from "libsodium-wrappers";
+
+import { getGitHubClient } from "@app/services/app-connection/github";
+import { GitHubSyncScope, GitHubSyncVisibility } from "@app/services/secret-sync/github/github-sync-enums";
+import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors";
+import { SECRET_SYNC_NAME_MAP } from "@app/services/secret-sync/secret-sync-maps";
+import { TSecretMap } from "@app/services/secret-sync/secret-sync-types";
+
+import { TGitHubPublicKey, TGitHubSecret, TGitHubSecretPayload, TGitHubSyncWithCredentials } from "./github-sync-types";
+
+// TODO: rate limit handling
+
+const getEncryptedSecrets = async (client: Octokit, secretSync: TGitHubSyncWithCredentials) => {
+  let encryptedSecrets: TGitHubSecret[];
+
+  const { destinationConfig } = secretSync;
+
+  switch (destinationConfig.scope) {
+    case GitHubSyncScope.Organization: {
+      encryptedSecrets = await client.paginate("GET /orgs/{org}/actions/secrets", {
+        org: destinationConfig.org
+      });
+      break;
+    }
+    case GitHubSyncScope.Repository: {
+      encryptedSecrets = await client.paginate("GET /repos/{owner}/{repo}/actions/secrets", {
+        owner: destinationConfig.owner,
+        repo: destinationConfig.repo
+      });
+
+      break;
+    }
+    case GitHubSyncScope.RepositoryEnvironment:
+    default: {
+      encryptedSecrets = await client.paginate("GET /repos/{owner}/{repo}/environments/{environment_name}/secrets", {
+        owner: destinationConfig.owner,
+        repo: destinationConfig.repo,
+        environment_name: destinationConfig.env
+      });
+      break;
+    }
+  }
+
+  return encryptedSecrets;
+};
+
+const getPublicKey = async (client: Octokit, secretSync: TGitHubSyncWithCredentials) => {
+  let publicKey: TGitHubPublicKey;
+
+  const { destinationConfig } = secretSync;
+
+  switch (destinationConfig.scope) {
+    case GitHubSyncScope.Organization: {
+      publicKey = (
+        await client.request("GET /orgs/{org}/actions/secrets/public-key", {
+          org: destinationConfig.org
+        })
+      ).data;
+      break;
+    }
+    case GitHubSyncScope.Repository: {
+      publicKey = (
+        await client.request("GET /repos/{owner}/{repo}/actions/secrets/public-key", {
+          owner: destinationConfig.owner,
+          repo: destinationConfig.repo
+        })
+      ).data;
+      break;
+    }
+    case GitHubSyncScope.RepositoryEnvironment:
+    default: {
+      publicKey = (
+        await client.request("GET /repos/{owner}/{repo}/environments/{environment_name}/secrets/public-key", {
+          owner: destinationConfig.owner,
+          repo: destinationConfig.repo,
+          environment_name: destinationConfig.env
+        })
+      ).data;
+      break;
+    }
+  }
+
+  return publicKey;
+};
+
+const deleteSecret = async (
+  client: Octokit,
+  secretSync: TGitHubSyncWithCredentials,
+  encryptedSecret: TGitHubSecret
+) => {
+  const { destinationConfig } = secretSync;
+
+  switch (destinationConfig.scope) {
+    case GitHubSyncScope.Organization: {
+      await client.request(`DELETE /orgs/{org}/actions/secrets/{secret_name}`, {
+        org: destinationConfig.org,
+        secret_name: encryptedSecret.name
+      });
+      break;
+    }
+    case GitHubSyncScope.Repository: {
+      await client.request("DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}", {
+        owner: destinationConfig.owner,
+        repo: destinationConfig.repo,
+        secret_name: encryptedSecret.name
+      });
+      break;
+    }
+    case GitHubSyncScope.RepositoryEnvironment:
+    default: {
+      await client.request("DELETE /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}", {
+        owner: destinationConfig.owner,
+        repo: destinationConfig.repo,
+        environment_name: destinationConfig.env,
+        secret_name: encryptedSecret.name
+      });
+      break;
+    }
+  }
+};
+
+const putSecret = async (client: Octokit, secretSync: TGitHubSyncWithCredentials, payload: TGitHubSecretPayload) => {
+  const { destinationConfig } = secretSync;
+
+  switch (destinationConfig.scope) {
+    case GitHubSyncScope.Organization: {
+      const { visibility, selectedRepositoryIds } = destinationConfig;
+
+      await client.request(`PUT /orgs/{org}/actions/secrets/{secret_name}`, {
+        org: destinationConfig.org,
+        ...payload,
+        visibility,
+        ...(visibility === GitHubSyncVisibility.Selected && {
+          selected_repository_ids: selectedRepositoryIds
+        })
+      });
+      break;
+    }
+    case GitHubSyncScope.Repository: {
+      await client.request("PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}", {
+        owner: destinationConfig.owner,
+        repo: destinationConfig.repo,
+        ...payload
+      });
+      break;
+    }
+    case GitHubSyncScope.RepositoryEnvironment:
+    default: {
+      await client.request("PUT /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}", {
+        owner: destinationConfig.owner,
+        repo: destinationConfig.repo,
+        environment_name: destinationConfig.env,
+        ...payload
+      });
+      break;
+    }
+  }
+};
+
+export const GithubSyncFns = {
+  syncSecrets: async (secretSync: TGitHubSyncWithCredentials, secretMap: TSecretMap) => {
+    switch (secretSync.destinationConfig.scope) {
+      case GitHubSyncScope.Organization:
+        if (Object.values(secretMap).length > 1000) {
+          throw new SecretSyncError({
+            message: "GitHub does not support storing more than 1,000 secrets at the organization level.",
+            shouldRetry: false
+          });
+        }
+        break;
+      case GitHubSyncScope.Repository:
+      case GitHubSyncScope.RepositoryEnvironment:
+        if (Object.values(secretMap).length > 100) {
+          throw new SecretSyncError({
+            message: "GitHub does not support storing more than 100 secrets at the repository level.",
+            shouldRetry: false
+          });
+        }
+        break;
+      default:
+        throw new Error(
+          `Unsupported GitHub Sync scope ${
+            (secretSync.destinationConfig as TGitHubSyncWithCredentials["destinationConfig"]).scope
+          }`
+        );
+    }
+
+    const client = getGitHubClient(secretSync.connection);
+
+    const encryptedSecrets = await getEncryptedSecrets(client, secretSync);
+
+    const publicKey = await getPublicKey(client, secretSync);
+
+    for await (const encryptedSecret of encryptedSecrets) {
+      if (!(encryptedSecret.name in secretMap)) {
+        await deleteSecret(client, secretSync, encryptedSecret);
+      }
+    }
+
+    await sodium.ready.then(async () => {
+      for await (const key of Object.keys(secretMap)) {
+        // convert secret & base64 key to Uint8Array.
+        const binaryKey = sodium.from_base64(publicKey.key, sodium.base64_variants.ORIGINAL);
+        const binarySecretValue = sodium.from_string(secretMap[key].value);
+
+        // encrypt secret using libsodium
+        const encryptedBytes = sodium.crypto_box_seal(binarySecretValue, binaryKey);
+
+        // convert encrypted Uint8Array to base64
+        const encryptedSecretValue = sodium.to_base64(encryptedBytes, sodium.base64_variants.ORIGINAL);
+
+        try {
+          await putSecret(client, secretSync, {
+            secret_name: key,
+            encrypted_value: encryptedSecretValue,
+            key_id: publicKey.key_id
+          });
+        } catch (error) {
+          throw new SecretSyncError({
+            error,
+            secretKey: key
+          });
+        }
+      }
+    });
+  },
+  getSecrets: async (secretSync: TGitHubSyncWithCredentials) => {
+    throw new Error(`${SECRET_SYNC_NAME_MAP[secretSync.destination]} does not support importing secrets.`);
+  },
+  removeSecrets: async (secretSync: TGitHubSyncWithCredentials, secretMap: TSecretMap) => {
+    const client = getGitHubClient(secretSync.connection);
+
+    const encryptedSecrets = await getEncryptedSecrets(client, secretSync);
+
+    for await (const encryptedSecret of encryptedSecrets) {
+      if (encryptedSecret.name in secretMap) {
+        await deleteSecret(client, secretSync, encryptedSecret);
+      }
+    }
+  }
+};
diff --git a/backend/src/services/secret-sync/github/github-sync-schemas.ts b/backend/src/services/secret-sync/github/github-sync-schemas.ts
new file mode 100644
index 0000000000..37a294a1be
--- /dev/null
+++ b/backend/src/services/secret-sync/github/github-sync-schemas.ts
@@ -0,0 +1,82 @@
+import { z } from "zod";
+
+import { SecretSyncs } from "@app/lib/api-docs";
+import { AppConnection } from "@app/services/app-connection/app-connection-enums";
+import { GitHubSyncScope, GitHubSyncVisibility } from "@app/services/secret-sync/github/github-sync-enums";
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+import {
+  BaseSecretSyncSchema,
+  GenericCreateSecretSyncFieldsSchema,
+  GenericUpdateSecretSyncFieldsSchema
+} from "@app/services/secret-sync/secret-sync-schemas";
+import { TSyncOptionsConfig } from "@app/services/secret-sync/secret-sync-types";
+
+const GitHubSyncDestinationConfigSchema = z
+  .discriminatedUnion("scope", [
+    z.object({
+      scope: z.literal(GitHubSyncScope.Organization),
+      org: z.string().min(1, "Organization name required").describe(SecretSyncs.DESTINATION_CONFIG.GITHUB.ORG),
+      visibility: z.nativeEnum(GitHubSyncVisibility),
+      selectedRepositoryIds: z.number().array().optional()
+    }),
+    z.object({
+      scope: z.literal(GitHubSyncScope.Repository),
+      owner: z.string().min(1, "Repository owner name required").describe(SecretSyncs.DESTINATION_CONFIG.GITHUB.OWNER),
+      repo: z.string().min(1, "Repository name required").describe(SecretSyncs.DESTINATION_CONFIG.GITHUB.REPO)
+    }),
+    z.object({
+      scope: z.literal(GitHubSyncScope.RepositoryEnvironment),
+      owner: z.string().min(1, "Repository owner name required").describe(SecretSyncs.DESTINATION_CONFIG.GITHUB.OWNER),
+      repo: z.string().min(1, "Repository name required").describe(SecretSyncs.DESTINATION_CONFIG.GITHUB.REPO),
+      env: z.string().min(1, "Environment name required").describe(SecretSyncs.DESTINATION_CONFIG.GITHUB.ENV)
+    })
+  ])
+  .superRefine((options, ctx) => {
+    if (options.scope === GitHubSyncScope.Organization) {
+      if (options.visibility === GitHubSyncVisibility.Selected) {
+        if (!options.selectedRepositoryIds?.length)
+          ctx.addIssue({
+            code: z.ZodIssueCode.custom,
+            message: "Select at least 1 repository",
+            path: ["selectedRepositoryIds"]
+          });
+        return;
+      }
+
+      if (options.selectedRepositoryIds?.length) {
+        ctx.addIssue({
+          code: z.ZodIssueCode.custom,
+          message: `Selected repositories is only supported for visibility "Selected"`,
+          path: ["selectedRepositoryIds"]
+        });
+      }
+    }
+  });
+
+const GitHubSyncOptionsConfig: TSyncOptionsConfig = { canImportSecrets: false };
+
+export const GitHubSyncSchema = BaseSecretSyncSchema(SecretSync.GitHub, GitHubSyncOptionsConfig).extend({
+  destination: z.literal(SecretSync.GitHub),
+  destinationConfig: GitHubSyncDestinationConfigSchema
+});
+
+export const CreateGitHubSyncSchema = GenericCreateSecretSyncFieldsSchema(
+  SecretSync.GitHub,
+  GitHubSyncOptionsConfig
+).extend({
+  destinationConfig: GitHubSyncDestinationConfigSchema
+});
+
+export const UpdateGitHubSyncSchema = GenericUpdateSecretSyncFieldsSchema(
+  SecretSync.GitHub,
+  GitHubSyncOptionsConfig
+).extend({
+  destinationConfig: GitHubSyncDestinationConfigSchema.optional()
+});
+
+export const GitHubSyncListItemSchema = z.object({
+  name: z.literal("GitHub"),
+  connection: z.literal(AppConnection.GitHub),
+  destination: z.literal(SecretSync.GitHub),
+  canImportSecrets: z.literal(false)
+});
diff --git a/backend/src/services/secret-sync/github/github-sync-types.ts b/backend/src/services/secret-sync/github/github-sync-types.ts
new file mode 100644
index 0000000000..c917a9fa4d
--- /dev/null
+++ b/backend/src/services/secret-sync/github/github-sync-types.ts
@@ -0,0 +1,38 @@
+import { z } from "zod";
+
+import { TGitHubConnection } from "@app/services/app-connection/github";
+
+import { CreateGitHubSyncSchema, GitHubSyncListItemSchema, GitHubSyncSchema } from "./github-sync-schemas";
+
+export type TGitHubSync = z.infer<typeof GitHubSyncSchema>;
+
+export type TGitHubSyncInput = z.infer<typeof CreateGitHubSyncSchema>;
+
+export type TGitHubSyncListItem = z.infer<typeof GitHubSyncListItemSchema>;
+
+export type TGitHubSyncWithCredentials = TGitHubSync & {
+  connection: TGitHubConnection;
+};
+
+export type TGitHubSecret = {
+  name: string;
+  created_at: string;
+  updated_at: string;
+  visibility?: "all" | "private" | "selected";
+  selected_repositories_url?: string | undefined;
+};
+
+export type TGitHubPublicKey = {
+  key_id: string;
+  key: string;
+  id?: number | undefined;
+  url?: string | undefined;
+  title?: string | undefined;
+  created_at?: string | undefined;
+};
+
+export type TGitHubSecretPayload = {
+  key_id: string;
+  secret_name: string;
+  encrypted_value: string;
+};
diff --git a/backend/src/services/secret-sync/github/index.ts b/backend/src/services/secret-sync/github/index.ts
new file mode 100644
index 0000000000..a136d77801
--- /dev/null
+++ b/backend/src/services/secret-sync/github/index.ts
@@ -0,0 +1,4 @@
+export * from "./github-sync-constants";
+export * from "./github-sync-fns";
+export * from "./github-sync-schemas";
+export * from "./github-sync-types";
diff --git a/backend/src/services/secret-sync/secret-sync-dal.ts b/backend/src/services/secret-sync/secret-sync-dal.ts
new file mode 100644
index 0000000000..8d99f8637c
--- /dev/null
+++ b/backend/src/services/secret-sync/secret-sync-dal.ts
@@ -0,0 +1,212 @@
+import { Knex } from "knex";
+
+import { TDbClient } from "@app/db";
+import { TableName } from "@app/db/schemas";
+import { TSecretSyncs } from "@app/db/schemas/secret-syncs";
+import { DatabaseError } from "@app/lib/errors";
+import { buildFindFilter, ormify, selectAllTableCols } from "@app/lib/knex";
+import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
+
+export type TSecretSyncDALFactory = ReturnType<typeof secretSyncDALFactory>;
+
+type SecretSyncFindFilter = Parameters<typeof buildFindFilter<TSecretSyncs>>[0];
+
+const baseSecretSyncQuery = ({ filter, db, tx }: { db: TDbClient; filter?: SecretSyncFindFilter; tx?: Knex }) => {
+  const query = (tx || db.replicaNode())(TableName.SecretSync)
+    .leftJoin(TableName.SecretFolder, `${TableName.SecretSync}.folderId`, `${TableName.SecretFolder}.id`)
+    .leftJoin(TableName.Environment, `${TableName.SecretFolder}.envId`, `${TableName.Environment}.id`)
+    .join(TableName.AppConnection, `${TableName.SecretSync}.connectionId`, `${TableName.AppConnection}.id`)
+    .select(selectAllTableCols(TableName.SecretSync))
+    .select(
+      // environment
+      db.ref("name").withSchema(TableName.Environment).as("envName"),
+      db.ref("id").withSchema(TableName.Environment).as("envId"),
+      db.ref("slug").withSchema(TableName.Environment).as("envSlug"),
+      // entire connection
+      db.ref("name").withSchema(TableName.AppConnection).as("connectionName"),
+      db.ref("method").withSchema(TableName.AppConnection).as("connectionMethod"),
+      db.ref("app").withSchema(TableName.AppConnection).as("connectionApp"),
+      db.ref("orgId").withSchema(TableName.AppConnection).as("connectionOrgId"),
+      db.ref("encryptedCredentials").withSchema(TableName.AppConnection).as("connectionEncryptedCredentials"),
+      db.ref("description").withSchema(TableName.AppConnection).as("connectionDescription"),
+      db.ref("version").withSchema(TableName.AppConnection).as("connectionVersion"),
+      db.ref("createdAt").withSchema(TableName.AppConnection).as("connectionCreatedAt"),
+      db.ref("updatedAt").withSchema(TableName.AppConnection).as("connectionUpdatedAt")
+    );
+
+  // prepends table name to filter keys to avoid ambiguous col references, skipping utility filters like $in, etc.
+  const prependTableName = (filterObj: object): SecretSyncFindFilter =>
+    Object.fromEntries(
+      Object.entries(filterObj).map(([key, value]) =>
+        key.startsWith("$") ? [key, prependTableName(value as object)] : [`${TableName.SecretSync}.${key}`, value]
+      )
+    );
+
+  if (filter) {
+    /* eslint-disable @typescript-eslint/no-misused-promises */
+    void query.where(buildFindFilter(prependTableName(filter)));
+  }
+
+  return query;
+};
+
+const expandSecretSync = (
+  secretSync: Awaited<ReturnType<typeof baseSecretSyncQuery>>[number],
+  folder?: Awaited<ReturnType<TSecretFolderDALFactory["findSecretPathByFolderIds"]>>[number]
+) => {
+  const {
+    envId,
+    envName,
+    envSlug,
+    connectionApp,
+    connectionName,
+    connectionId,
+    connectionOrgId,
+    connectionEncryptedCredentials,
+    connectionMethod,
+    connectionDescription,
+    connectionCreatedAt,
+    connectionUpdatedAt,
+    connectionVersion,
+    ...el
+  } = secretSync;
+
+  return {
+    ...el,
+    connectionId,
+    environment: envId ? { id: envId, name: envName, slug: envSlug } : null,
+    connection: {
+      app: connectionApp,
+      id: connectionId,
+      name: connectionName,
+      orgId: connectionOrgId,
+      encryptedCredentials: connectionEncryptedCredentials,
+      method: connectionMethod,
+      description: connectionDescription,
+      createdAt: connectionCreatedAt,
+      updatedAt: connectionUpdatedAt,
+      version: connectionVersion
+    },
+    folder: folder
+      ? {
+          id: folder.id,
+          path: folder.path
+        }
+      : null
+  };
+};
+
+export const secretSyncDALFactory = (
+  db: TDbClient,
+  folderDAL: Pick<TSecretFolderDALFactory, "findSecretPathByFolderIds">
+) => {
+  const secretSyncOrm = ormify(db, TableName.SecretSync);
+
+  const findById = async (id: string, tx?: Knex) => {
+    try {
+      const secretSync = await baseSecretSyncQuery({
+        filter: { id },
+        db,
+        tx
+      }).first();
+
+      if (secretSync) {
+        // TODO (scott): replace with cached folder path once implemented
+        const [folderWithPath] = secretSync.folderId
+          ? await folderDAL.findSecretPathByFolderIds(secretSync.projectId, [secretSync.folderId])
+          : [];
+        return expandSecretSync(secretSync, folderWithPath);
+      }
+    } catch (error) {
+      throw new DatabaseError({ error, name: "Find by ID - Secret Sync" });
+    }
+  };
+
+  const create = async (data: Parameters<(typeof secretSyncOrm)["create"]>[0]) => {
+    try {
+      const secretSync = (await secretSyncOrm.transaction(async (tx) => {
+        const sync = await secretSyncOrm.create(data, tx);
+
+        return baseSecretSyncQuery({
+          filter: { id: sync.id },
+          db,
+          tx
+        }).first();
+      }))!;
+
+      // TODO (scott): replace with cached folder path once implemented
+      const [folderWithPath] = secretSync.folderId
+        ? await folderDAL.findSecretPathByFolderIds(secretSync.projectId, [secretSync.folderId])
+        : [];
+      return expandSecretSync(secretSync, folderWithPath);
+    } catch (error) {
+      throw new DatabaseError({ error, name: "Create - Secret Sync" });
+    }
+  };
+
+  const updateById = async (syncId: string, data: Parameters<(typeof secretSyncOrm)["updateById"]>[1]) => {
+    try {
+      const secretSync = (await secretSyncOrm.transaction(async (tx) => {
+        const sync = await secretSyncOrm.updateById(syncId, data, tx);
+
+        return baseSecretSyncQuery({
+          filter: { id: sync.id },
+          db,
+          tx
+        }).first();
+      }))!;
+
+      // TODO (scott): replace with cached folder path once implemented
+      const [folderWithPath] = secretSync.folderId
+        ? await folderDAL.findSecretPathByFolderIds(secretSync.projectId, [secretSync.folderId])
+        : [];
+      return expandSecretSync(secretSync, folderWithPath);
+    } catch (error) {
+      throw new DatabaseError({ error, name: "Update by ID - Secret Sync" });
+    }
+  };
+
+  const findOne = async (filter: Parameters<(typeof secretSyncOrm)["findOne"]>[0], tx?: Knex) => {
+    try {
+      const secretSync = await baseSecretSyncQuery({ filter, db, tx }).first();
+
+      if (secretSync) {
+        // TODO (scott): replace with cached folder path once implemented
+        const [folderWithPath] = secretSync.folderId
+          ? await folderDAL.findSecretPathByFolderIds(secretSync.projectId, [secretSync.folderId])
+          : [];
+        return expandSecretSync(secretSync, folderWithPath);
+      }
+    } catch (error) {
+      throw new DatabaseError({ error, name: "Find One - Secret Sync" });
+    }
+  };
+
+  const find = async (filter: Parameters<(typeof secretSyncOrm)["find"]>[0], tx?: Knex) => {
+    try {
+      const secretSyncs = await baseSecretSyncQuery({ filter, db, tx });
+
+      if (!secretSyncs.length) return [];
+
+      const foldersWithPath = await folderDAL.findSecretPathByFolderIds(
+        secretSyncs[0].projectId,
+        secretSyncs.filter((sync) => Boolean(sync.folderId)).map((sync) => sync.folderId!)
+      );
+
+      // TODO (scott): replace with cached folder path once implemented
+      const folderRecord: Record<string, (typeof foldersWithPath)[number]> = {};
+
+      foldersWithPath.forEach((folder) => {
+        if (folder) folderRecord[folder.id] = folder;
+      });
+
+      return secretSyncs.map((secretSync) =>
+        expandSecretSync(secretSync, secretSync.folderId ? folderRecord[secretSync.folderId] : undefined)
+      );
+    } catch (error) {
+      throw new DatabaseError({ error, name: "Find - Secret Sync" });
+    }
+  };
+
+  return { ...secretSyncOrm, findById, findOne, find, create, updateById };
+};
diff --git a/backend/src/services/secret-sync/secret-sync-enums.ts b/backend/src/services/secret-sync/secret-sync-enums.ts
new file mode 100644
index 0000000000..406a3a1615
--- /dev/null
+++ b/backend/src/services/secret-sync/secret-sync-enums.ts
@@ -0,0 +1,15 @@
+export enum SecretSync {
+  AWSParameterStore = "aws-parameter-store",
+  GitHub = "github"
+}
+
+export enum SecretSyncInitialSyncBehavior {
+  OverwriteDestination = "overwrite-destination",
+  ImportPrioritizeSource = "import-prioritize-source",
+  ImportPrioritizeDestination = "import-prioritize-destination"
+}
+
+export enum SecretSyncImportBehavior {
+  PrioritizeSource = "prioritize-source",
+  PrioritizeDestination = "prioritize-destination"
+}
diff --git a/backend/src/services/secret-sync/secret-sync-errors.ts b/backend/src/services/secret-sync/secret-sync-errors.ts
new file mode 100644
index 0000000000..859fbb00dc
--- /dev/null
+++ b/backend/src/services/secret-sync/secret-sync-errors.ts
@@ -0,0 +1,23 @@
+export class SecretSyncError extends Error {
+  name: string;
+
+  error?: unknown;
+
+  secretKey?: string;
+
+  shouldRetry?: boolean;
+
+  constructor({
+    name,
+    error,
+    secretKey,
+    message,
+    shouldRetry = true
+  }: { name?: string; error?: unknown; secretKey?: string; shouldRetry?: boolean; message?: string } = {}) {
+    super(message);
+    this.name = name || "SecretSyncError";
+    this.error = error;
+    this.secretKey = secretKey;
+    this.shouldRetry = shouldRetry;
+  }
+}
diff --git a/backend/src/services/secret-sync/secret-sync-fns.ts b/backend/src/services/secret-sync/secret-sync-fns.ts
new file mode 100644
index 0000000000..de39fef02f
--- /dev/null
+++ b/backend/src/services/secret-sync/secret-sync-fns.ts
@@ -0,0 +1,127 @@
+import { AxiosError } from "axios";
+
+import {
+  AWS_PARAMETER_STORE_SYNC_LIST_OPTION,
+  AwsParameterStoreSyncFns
+} from "@app/services/secret-sync/aws-parameter-store";
+import { GITHUB_SYNC_LIST_OPTION, GithubSyncFns } from "@app/services/secret-sync/github";
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors";
+import {
+  TSecretMap,
+  TSecretSyncListItem,
+  TSecretSyncWithCredentials
+} from "@app/services/secret-sync/secret-sync-types";
+
+const SECRET_SYNC_LIST_OPTIONS: Record<SecretSync, TSecretSyncListItem> = {
+  [SecretSync.AWSParameterStore]: AWS_PARAMETER_STORE_SYNC_LIST_OPTION,
+  [SecretSync.GitHub]: GITHUB_SYNC_LIST_OPTION
+};
+
+export const listSecretSyncOptions = () => {
+  return Object.values(SECRET_SYNC_LIST_OPTIONS).sort((a, b) => a.name.localeCompare(b.name));
+};
+
+// const addAffixes = (secretSync: TSecretSyncWithCredentials, unprocessedSecretMap: TSecretMap) => {
+//   let secretMap = { ...unprocessedSecretMap };
+//
+//   const { appendSuffix, prependPrefix } = secretSync.syncOptions;
+//
+//   if (appendSuffix || prependPrefix) {
+//     secretMap = {};
+//     Object.entries(unprocessedSecretMap).forEach(([key, value]) => {
+//       secretMap[`${prependPrefix || ""}${key}${appendSuffix || ""}`] = value;
+//     });
+//   }
+//
+//   return secretMap;
+// };
+//
+// const stripAffixes = (secretSync: TSecretSyncWithCredentials, unprocessedSecretMap: TSecretMap) => {
+//   let secretMap = { ...unprocessedSecretMap };
+//
+//   const { appendSuffix, prependPrefix } = secretSync.syncOptions;
+//
+//   if (appendSuffix || prependPrefix) {
+//     secretMap = {};
+//     Object.entries(unprocessedSecretMap).forEach(([key, value]) => {
+//       let processedKey = key;
+//
+//       if (prependPrefix && processedKey.startsWith(prependPrefix)) {
+//         processedKey = processedKey.slice(prependPrefix.length);
+//       }
+//
+//       if (appendSuffix && processedKey.endsWith(appendSuffix)) {
+//         processedKey = processedKey.slice(0, -appendSuffix.length);
+//       }
+//
+//       secretMap[processedKey] = value;
+//     });
+//   }
+//
+//   return secretMap;
+// };
+
+export const SecretSyncFns = {
+  syncSecrets: (secretSync: TSecretSyncWithCredentials, secretMap: TSecretMap): Promise<void> => {
+    // const affixedSecretMap = addAffixes(secretSync, secretMap);
+
+    switch (secretSync.destination) {
+      case SecretSync.AWSParameterStore:
+        return AwsParameterStoreSyncFns.syncSecrets(secretSync, secretMap);
+      case SecretSync.GitHub:
+        return GithubSyncFns.syncSecrets(secretSync, secretMap);
+      default:
+        throw new Error(
+          `Unhandled sync destination for sync secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}`
+        );
+    }
+  },
+  getSecrets: async (secretSync: TSecretSyncWithCredentials): Promise<TSecretMap> => {
+    let secretMap: TSecretMap;
+    switch (secretSync.destination) {
+      case SecretSync.AWSParameterStore:
+        secretMap = await AwsParameterStoreSyncFns.getSecrets(secretSync);
+        break;
+      case SecretSync.GitHub:
+        secretMap = await GithubSyncFns.getSecrets(secretSync);
+        break;
+      default:
+        throw new Error(
+          `Unhandled sync destination for get secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}`
+        );
+    }
+
+    return secretMap;
+    // return stripAffixes(secretSync, secretMap);
+  },
+  removeSecrets: (secretSync: TSecretSyncWithCredentials, secretMap: TSecretMap): Promise<void> => {
+    // const affixedSecretMap = addAffixes(secretSync, secretMap);
+
+    switch (secretSync.destination) {
+      case SecretSync.AWSParameterStore:
+        return AwsParameterStoreSyncFns.removeSecrets(secretSync, secretMap);
+      case SecretSync.GitHub:
+        return GithubSyncFns.removeSecrets(secretSync, secretMap);
+      default:
+        throw new Error(
+          `Unhandled sync destination for remove secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}`
+        );
+    }
+  }
+};
+
+export const parseSyncErrorMessage = (err: unknown): string => {
+  if (err instanceof SecretSyncError) {
+    return JSON.stringify({
+      secretKey: err.secretKey,
+      error: err.message ?? parseSyncErrorMessage(err.error)
+    });
+  }
+
+  if (err instanceof AxiosError) {
+    return err?.response?.data ? JSON.stringify(err?.response?.data) : err?.message ?? "An unknown error occurred.";
+  }
+
+  return (err as Error)?.message || "An unknown error occurred.";
+};
diff --git a/backend/src/services/secret-sync/secret-sync-maps.ts b/backend/src/services/secret-sync/secret-sync-maps.ts
new file mode 100644
index 0000000000..67ba7b6903
--- /dev/null
+++ b/backend/src/services/secret-sync/secret-sync-maps.ts
@@ -0,0 +1,12 @@
+import { AppConnection } from "@app/services/app-connection/app-connection-enums";
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+
+export const SECRET_SYNC_NAME_MAP: Record<SecretSync, string> = {
+  [SecretSync.AWSParameterStore]: "AWS Parameter Store",
+  [SecretSync.GitHub]: "GitHub"
+};
+
+export const SECRET_SYNC_CONNECTION_MAP: Record<SecretSync, AppConnection> = {
+  [SecretSync.AWSParameterStore]: AppConnection.AWS,
+  [SecretSync.GitHub]: AppConnection.GitHub
+};
diff --git a/backend/src/services/secret-sync/secret-sync-queue.ts b/backend/src/services/secret-sync/secret-sync-queue.ts
new file mode 100644
index 0000000000..d2bcdb590a
--- /dev/null
+++ b/backend/src/services/secret-sync/secret-sync-queue.ts
@@ -0,0 +1,955 @@
+import opentelemetry from "@opentelemetry/api";
+import { AxiosError } from "axios";
+import { Job } from "bullmq";
+
+import { ProjectMembershipRole, SecretType } from "@app/db/schemas";
+import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
+import { EventType } from "@app/ee/services/audit-log/audit-log-types";
+import { KeyStorePrefixes, TKeyStoreFactory } from "@app/keystore/keystore";
+import { getConfig } from "@app/lib/config/env";
+import { logger } from "@app/lib/logger";
+import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
+import { decryptAppConnectionCredentials } from "@app/services/app-connection/app-connection-fns";
+import { ActorType } from "@app/services/auth/auth-type";
+import { TKmsServiceFactory } from "@app/services/kms/kms-service";
+import { KmsDataKey } from "@app/services/kms/kms-types";
+import { TProjectDALFactory } from "@app/services/project/project-dal";
+import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal";
+import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
+import { TResourceMetadataDALFactory } from "@app/services/resource-metadata/resource-metadata-dal";
+import { TSecretDALFactory } from "@app/services/secret/secret-dal";
+import { createManySecretsRawFnFactory, updateManySecretsRawFnFactory } from "@app/services/secret/secret-fns";
+import { TSecretVersionDALFactory } from "@app/services/secret/secret-version-dal";
+import { TSecretVersionTagDALFactory } from "@app/services/secret/secret-version-tag-dal";
+import { TSecretBlindIndexDALFactory } from "@app/services/secret-blind-index/secret-blind-index-dal";
+import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
+import { TSecretImportDALFactory } from "@app/services/secret-import/secret-import-dal";
+import { fnSecretsV2FromImports } from "@app/services/secret-import/secret-import-fns";
+import { TSecretSyncDALFactory } from "@app/services/secret-sync/secret-sync-dal";
+import {
+  SecretSync,
+  SecretSyncImportBehavior,
+  SecretSyncInitialSyncBehavior
+} from "@app/services/secret-sync/secret-sync-enums";
+import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors";
+import { parseSyncErrorMessage, SecretSyncFns } from "@app/services/secret-sync/secret-sync-fns";
+import { SECRET_SYNC_NAME_MAP } from "@app/services/secret-sync/secret-sync-maps";
+import {
+  SecretSyncAction,
+  SecretSyncStatus,
+  TQueueSecretSyncImportSecretsByIdDTO,
+  TQueueSecretSyncRemoveSecretsByIdDTO,
+  TQueueSecretSyncsByPathDTO,
+  TQueueSecretSyncSyncSecretsByIdDTO,
+  TQueueSendSecretSyncActionFailedNotificationsDTO,
+  TSecretMap,
+  TSecretSyncImportSecretsDTO,
+  TSecretSyncRaw,
+  TSecretSyncRemoveSecretsDTO,
+  TSecretSyncSyncSecretsDTO,
+  TSecretSyncWithCredentials,
+  TSendSecretSyncFailedNotificationsJobDTO
+} from "@app/services/secret-sync/secret-sync-types";
+import { TSecretTagDALFactory } from "@app/services/secret-tag/secret-tag-dal";
+import { TSecretV2BridgeDALFactory } from "@app/services/secret-v2-bridge/secret-v2-bridge-dal";
+import { expandSecretReferencesFactory } from "@app/services/secret-v2-bridge/secret-v2-bridge-fns";
+import { TSecretVersionV2DALFactory } from "@app/services/secret-v2-bridge/secret-version-dal";
+import { TSecretVersionV2TagDALFactory } from "@app/services/secret-v2-bridge/secret-version-tag-dal";
+import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service";
+
+export type TSecretSyncQueueFactory = ReturnType<typeof secretSyncQueueFactory>;
+
+type TSecretSyncQueueFactoryDep = {
+  queueService: Pick<TQueueServiceFactory, "queue" | "start">;
+  kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
+  keyStore: Pick<TKeyStoreFactory, "acquireLock" | "setItemWithExpiry" | "getItem">;
+  folderDAL: TSecretFolderDALFactory;
+  secretV2BridgeDAL: Pick<
+    TSecretV2BridgeDALFactory,
+    | "findByFolderId"
+    | "find"
+    | "insertMany"
+    | "upsertSecretReferences"
+    | "findBySecretKeys"
+    | "bulkUpdate"
+    | "deleteMany"
+  >;
+  secretImportDAL: Pick<TSecretImportDALFactory, "find" | "findByFolderIds">;
+  secretSyncDAL: Pick<TSecretSyncDALFactory, "findById" | "find" | "updateById" | "deleteById">;
+  auditLogService: Pick<TAuditLogServiceFactory, "createAuditLog">;
+  projectMembershipDAL: Pick<TProjectMembershipDALFactory, "findAllProjectMembers">;
+  projectDAL: TProjectDALFactory;
+  smtpService: Pick<TSmtpService, "sendMail">;
+  projectBotDAL: TProjectBotDALFactory;
+  secretDAL: TSecretDALFactory;
+  secretVersionDAL: TSecretVersionDALFactory;
+  secretBlindIndexDAL: TSecretBlindIndexDALFactory;
+  secretTagDAL: TSecretTagDALFactory;
+  secretVersionTagDAL: TSecretVersionTagDALFactory;
+  secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">;
+  secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
+  resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
+};
+
+type SecretSyncActionJob = Job<
+  TQueueSecretSyncSyncSecretsByIdDTO | TQueueSecretSyncImportSecretsByIdDTO | TQueueSecretSyncRemoveSecretsByIdDTO
+>;
+
+const getRequeueDelay = (failureCount?: number) => {
+  if (!failureCount) return 0;
+
+  const baseDelay = 1000;
+  const maxDelay = 30000;
+
+  const delay = Math.min(baseDelay * 2 ** failureCount, maxDelay);
+
+  const jitter = delay * (0.5 + Math.random() * 0.5);
+
+  return jitter;
+};
+
+export const secretSyncQueueFactory = ({
+  queueService,
+  kmsService,
+  keyStore,
+  folderDAL,
+  secretV2BridgeDAL,
+  secretImportDAL,
+  secretSyncDAL,
+  auditLogService,
+  projectMembershipDAL,
+  projectDAL,
+  smtpService,
+  projectBotDAL,
+  secretDAL,
+  secretVersionDAL,
+  secretBlindIndexDAL,
+  secretTagDAL,
+  secretVersionTagDAL,
+  secretVersionV2BridgeDAL,
+  secretVersionTagV2BridgeDAL,
+  resourceMetadataDAL
+}: TSecretSyncQueueFactoryDep) => {
+  const appCfg = getConfig();
+
+  const integrationMeter = opentelemetry.metrics.getMeter("SecretSyncs");
+  const syncSecretsErrorHistogram = integrationMeter.createHistogram("secret_sync_sync_secrets_errors", {
+    description: "Secret Sync - sync secrets errors",
+    unit: "1"
+  });
+  const importSecretsErrorHistogram = integrationMeter.createHistogram("secret_sync_import_secrets_errors", {
+    description: "Secret Sync - import secrets errors",
+    unit: "1"
+  });
+  const removeSecretsErrorHistogram = integrationMeter.createHistogram("secret_sync_remove_secrets_errors", {
+    description: "Secret Sync - remove secrets errors",
+    unit: "1"
+  });
+
+  const $createManySecretsRawFn = createManySecretsRawFnFactory({
+    projectDAL,
+    projectBotDAL,
+    secretDAL,
+    secretVersionDAL,
+    secretBlindIndexDAL,
+    secretTagDAL,
+    secretVersionTagDAL,
+    folderDAL,
+    kmsService,
+    secretVersionV2BridgeDAL,
+    secretV2BridgeDAL,
+    secretVersionTagV2BridgeDAL,
+    resourceMetadataDAL
+  });
+
+  const $updateManySecretsRawFn = updateManySecretsRawFnFactory({
+    projectDAL,
+    projectBotDAL,
+    secretDAL,
+    secretVersionDAL,
+    secretBlindIndexDAL,
+    secretTagDAL,
+    secretVersionTagDAL,
+    folderDAL,
+    kmsService,
+    secretVersionV2BridgeDAL,
+    secretV2BridgeDAL,
+    secretVersionTagV2BridgeDAL,
+    resourceMetadataDAL
+  });
+
+  const $getInfisicalSecrets = async (
+    secretSync: TSecretSyncRaw | TSecretSyncWithCredentials,
+    includeImports = true
+  ) => {
+    const { projectId, folderId, environment, folder } = secretSync;
+
+    if (!folderId || !environment || !folder)
+      throw new SecretSyncError({
+        message:
+          "Invalid Secret Sync source configuration: folder no longer exists. Please update source environment and secret path.",
+        shouldRetry: false
+      });
+
+    const secretMap: TSecretMap = {};
+
+    const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
+      type: KmsDataKey.SecretManager,
+      projectId
+    });
+
+    const decryptSecretValue = (value?: Buffer | undefined | null) =>
+      value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : "";
+
+    const { expandSecretReferences } = expandSecretReferencesFactory({
+      decryptSecretValue,
+      secretDAL: secretV2BridgeDAL,
+      folderDAL,
+      projectId,
+      canExpandValue: () => true
+    });
+
+    const secrets = await secretV2BridgeDAL.findByFolderId(folderId);
+
+    await Promise.allSettled(
+      secrets.map(async (secret) => {
+        const secretKey = secret.key;
+        const secretValue = decryptSecretValue(secret.encryptedValue);
+        const expandedSecretValue = await expandSecretReferences({
+          environment: environment.slug,
+          secretPath: folder.path,
+          skipMultilineEncoding: secret.skipMultilineEncoding,
+          value: secretValue
+        });
+        secretMap[secretKey] = { value: expandedSecretValue || "" };
+
+        if (secret.encryptedComment) {
+          const commentValue = decryptSecretValue(secret.encryptedComment);
+          secretMap[secretKey].comment = commentValue;
+        }
+
+        secretMap[secretKey].skipMultilineEncoding = Boolean(secret.skipMultilineEncoding);
+      })
+    );
+
+    if (!includeImports) return secretMap;
+
+    const secretImports = await secretImportDAL.find({ folderId, isReplication: false });
+
+    if (secretImports.length) {
+      const importedSecrets = await fnSecretsV2FromImports({
+        decryptor: decryptSecretValue,
+        folderDAL,
+        secretDAL: secretV2BridgeDAL,
+        expandSecretReferences,
+        secretImportDAL,
+        secretImports,
+        hasSecretAccess: () => true
+      });
+
+      for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
+        for (let j = 0; j < importedSecrets[i].secrets.length; j += 1) {
+          const importedSecret = importedSecrets[i].secrets[j];
+          if (!secretMap[importedSecret.key]) {
+            secretMap[importedSecret.key] = {
+              skipMultilineEncoding: importedSecret.skipMultilineEncoding,
+              comment: importedSecret.secretComment,
+              value: importedSecret.secretValue || ""
+            };
+          }
+        }
+      }
+    }
+
+    return secretMap;
+  };
+
+  const queueSecretSyncSyncSecretsById = async (payload: TQueueSecretSyncSyncSecretsByIdDTO) =>
+    queueService.queue(QueueName.AppConnectionSecretSync, QueueJobs.SecretSyncSyncSecrets, payload, {
+      delay: getRequeueDelay(payload.failedToAcquireLockCount), // this is for delaying re-queued jobs if sync is locked
+      attempts: 5,
+      backoff: {
+        type: "exponential",
+        delay: 3000
+      },
+      removeOnComplete: true,
+      removeOnFail: true
+    });
+
+  const queueSecretSyncImportSecretsById = async (payload: TQueueSecretSyncImportSecretsByIdDTO) =>
+    queueService.queue(QueueName.AppConnectionSecretSync, QueueJobs.SecretSyncImportSecrets, payload, {
+      attempts: 1,
+      removeOnComplete: true,
+      removeOnFail: true
+    });
+
+  const queueSecretSyncRemoveSecretsById = async (payload: TQueueSecretSyncRemoveSecretsByIdDTO) =>
+    queueService.queue(QueueName.AppConnectionSecretSync, QueueJobs.SecretSyncRemoveSecrets, payload, {
+      attempts: 1,
+      removeOnComplete: true,
+      removeOnFail: true
+    });
+
+  const $queueSendSecretSyncFailedNotifications = async (payload: TQueueSendSecretSyncActionFailedNotificationsDTO) => {
+    if (!appCfg.isSmtpConfigured) return;
+
+    await queueService.queue(
+      QueueName.AppConnectionSecretSync,
+      QueueJobs.SecretSyncSendActionFailedNotifications,
+      payload,
+      {
+        jobId: `secret-sync-${payload.secretSync.id}-failed-notifications`,
+        attempts: 5,
+        delay: 1000 * 60,
+        backoff: {
+          type: "exponential",
+          delay: 3000
+        },
+        removeOnFail: true,
+        removeOnComplete: true
+      }
+    );
+  };
+
+  const $importSecrets = async (
+    secretSync: TSecretSyncWithCredentials,
+    importBehavior: SecretSyncImportBehavior
+  ): Promise<TSecretMap> => {
+    const { projectId, environment, folder } = secretSync;
+
+    if (!environment || !folder)
+      throw new Error(
+        "Invalid Secret Sync source configuration: folder no longer exists. Please update source environment and secret path."
+      );
+
+    const importedSecrets = await SecretSyncFns.getSecrets(secretSync);
+
+    if (!Object.keys(importedSecrets).length) return {};
+
+    const importedSecretMap: TSecretMap = {};
+
+    const secretMap = await $getInfisicalSecrets(secretSync, false);
+
+    const secretsToCreate: Parameters<typeof $createManySecretsRawFn>[0]["secrets"] = [];
+    const secretsToUpdate: Parameters<typeof $updateManySecretsRawFn>[0]["secrets"] = [];
+
+    Object.entries(importedSecrets).forEach(([key, secretData]) => {
+      const { value, comment = "", skipMultilineEncoding } = secretData;
+
+      const secret = {
+        secretName: key,
+        secretValue: value,
+        type: SecretType.Shared,
+        secretComment: comment,
+        skipMultilineEncoding: skipMultilineEncoding ?? undefined
+      };
+
+      if (Object.hasOwn(secretMap, key)) {
+        secretsToUpdate.push(secret);
+        if (importBehavior === SecretSyncImportBehavior.PrioritizeDestination) importedSecretMap[key] = secretData;
+      } else {
+        secretsToCreate.push(secret);
+        importedSecretMap[key] = secretData;
+      }
+    });
+
+    if (secretsToCreate.length) {
+      await $createManySecretsRawFn({
+        projectId,
+        path: folder.path,
+        environment: environment.slug,
+        secrets: secretsToCreate
+      });
+    }
+
+    if (importBehavior === SecretSyncImportBehavior.PrioritizeDestination && secretsToUpdate.length) {
+      await $updateManySecretsRawFn({
+        projectId,
+        path: folder.path,
+        environment: environment.slug,
+        secrets: secretsToUpdate
+      });
+    }
+
+    return importedSecretMap;
+  };
+
+  const $handleSyncSecretsJob = async (job: TSecretSyncSyncSecretsDTO) => {
+    const {
+      data: { syncId, auditLogInfo }
+    } = job;
+
+    const secretSync = await secretSyncDAL.findById(syncId);
+
+    if (!secretSync) throw new Error(`Cannot find secret sync with ID ${syncId}`);
+
+    await secretSyncDAL.updateById(syncId, {
+      syncStatus: SecretSyncStatus.Running
+    });
+
+    logger.info(
+      `SecretSync Sync [syncId=${secretSync.id}] [destination=${secretSync.destination}] [projectId=${secretSync.projectId}] [folderId=${secretSync.folderId}] [connectionId=${secretSync.connectionId}]`
+    );
+
+    let isSynced = false;
+    let syncMessage: string | null = null;
+    let isFinalAttempt = job.attemptsStarted === job.opts.attempts;
+
+    try {
+      const {
+        connection: { orgId, encryptedCredentials }
+      } = secretSync;
+
+      const credentials = await decryptAppConnectionCredentials({
+        orgId,
+        encryptedCredentials,
+        kmsService
+      });
+
+      const secretSyncWithCredentials = {
+        ...secretSync,
+        connection: {
+          ...secretSync.connection,
+          credentials
+        }
+      } as TSecretSyncWithCredentials;
+
+      const {
+        lastSyncedAt,
+        syncOptions: { initialSyncBehavior }
+      } = secretSyncWithCredentials;
+
+      const secretMap = await $getInfisicalSecrets(secretSync);
+
+      if (!lastSyncedAt && initialSyncBehavior !== SecretSyncInitialSyncBehavior.OverwriteDestination) {
+        const importedSecretMap = await $importSecrets(
+          secretSyncWithCredentials,
+          initialSyncBehavior === SecretSyncInitialSyncBehavior.ImportPrioritizeSource
+            ? SecretSyncImportBehavior.PrioritizeSource
+            : SecretSyncImportBehavior.PrioritizeDestination
+        );
+
+        Object.entries(importedSecretMap).forEach(([key, secretData]) => {
+          secretMap[key] = secretData;
+        });
+      }
+
+      await SecretSyncFns.syncSecrets(secretSyncWithCredentials, secretMap);
+
+      isSynced = true;
+    } catch (err) {
+      logger.error(
+        err,
+        `SecretSync Sync Error [syncId=${secretSync.id}] [destination=${secretSync.destination}] [projectId=${secretSync.projectId}] [folderId=${secretSync.folderId}] [connectionId=${secretSync.connectionId}]`
+      );
+
+      if (appCfg.OTEL_TELEMETRY_COLLECTION_ENABLED) {
+        syncSecretsErrorHistogram.record(1, {
+          version: 1,
+          destination: secretSync.destination,
+          syncId: secretSync.id,
+          projectId: secretSync.projectId,
+          type: err instanceof AxiosError ? "AxiosError" : err?.constructor?.name || "UnknownError",
+          status: err instanceof AxiosError ? err.response?.status : undefined,
+          name: err instanceof Error ? err.name : undefined
+        });
+      }
+
+      syncMessage = parseSyncErrorMessage(err);
+
+      if (err instanceof SecretSyncError && !err.shouldRetry) {
+        isFinalAttempt = true;
+      } else {
+        // re-throw so job fails
+        throw err;
+      }
+    } finally {
+      const ranAt = new Date();
+      const syncStatus = isSynced ? SecretSyncStatus.Succeeded : SecretSyncStatus.Failed;
+
+      await auditLogService.createAuditLog({
+        projectId: secretSync.projectId,
+        ...(auditLogInfo ?? {
+          actor: {
+            type: ActorType.PLATFORM,
+            metadata: {}
+          }
+        }),
+        event: {
+          type: EventType.SECRET_SYNC_SYNC_SECRETS,
+          metadata: {
+            syncId: secretSync.id,
+            syncOptions: secretSync.syncOptions,
+            destination: secretSync.destination,
+            destinationConfig: secretSync.destinationConfig,
+            folderId: secretSync.folderId,
+            connectionId: secretSync.connectionId,
+            jobRanAt: ranAt,
+            jobId: job.id!,
+            syncStatus,
+            syncMessage
+          }
+        }
+      });
+
+      if (isSynced || isFinalAttempt) {
+        const updatedSecretSync = await secretSyncDAL.updateById(secretSync.id, {
+          syncStatus,
+          lastSyncJobId: job.id,
+          lastSyncMessage: syncMessage,
+          lastSyncedAt: isSynced ? ranAt : undefined
+        });
+
+        if (!isSynced) {
+          await $queueSendSecretSyncFailedNotifications({
+            secretSync: updatedSecretSync,
+            action: SecretSyncAction.SyncSecrets,
+            auditLogInfo
+          });
+        }
+      }
+    }
+
+    logger.info("SecretSync Sync Job with ID %s Completed", job.id);
+  };
+
+  const $handleImportSecretsJob = async (job: TSecretSyncImportSecretsDTO) => {
+    const {
+      data: { syncId, auditLogInfo, importBehavior }
+    } = job;
+
+    const secretSync = await secretSyncDAL.findById(syncId);
+
+    if (!secretSync) throw new Error(`Cannot find secret sync with ID ${syncId}`);
+
+    await secretSyncDAL.updateById(syncId, {
+      importStatus: SecretSyncStatus.Running
+    });
+
+    logger.info(
+      `SecretSync Import [syncId=${secretSync.id}] [destination=${secretSync.destination}] [projectId=${secretSync.projectId}] [folderId=${secretSync.folderId}] [connectionId=${secretSync.connectionId}]`
+    );
+
+    let isSuccess = false;
+    let importMessage: string | null = null;
+    const isFinalAttempt = job.attemptsStarted === job.opts.attempts;
+
+    try {
+      const {
+        connection: { orgId, encryptedCredentials }
+      } = secretSync;
+
+      const credentials = await decryptAppConnectionCredentials({
+        orgId,
+        encryptedCredentials,
+        kmsService
+      });
+
+      await $importSecrets(
+        {
+          ...secretSync,
+          connection: {
+            ...secretSync.connection,
+            credentials
+          }
+        } as TSecretSyncWithCredentials,
+        importBehavior
+      );
+
+      isSuccess = true;
+    } catch (err) {
+      logger.error(
+        err,
+        `SecretSync Import Error [syncId=${secretSync.id}] [destination=${secretSync.destination}] [projectId=${secretSync.projectId}] [folderId=${secretSync.folderId}] [connectionId=${secretSync.connectionId}]`
+      );
+
+      if (appCfg.OTEL_TELEMETRY_COLLECTION_ENABLED) {
+        importSecretsErrorHistogram.record(1, {
+          version: 1,
+          destination: secretSync.destination,
+          syncId: secretSync.id,
+          projectId: secretSync.projectId,
+          type: err instanceof AxiosError ? "AxiosError" : err?.constructor?.name || "UnknownError",
+          status: err instanceof AxiosError ? err.response?.status : undefined,
+          name: err instanceof Error ? err.name : undefined
+        });
+      }
+
+      importMessage = parseSyncErrorMessage(err);
+
+      // re-throw so job fails
+      throw err;
+    } finally {
+      const ranAt = new Date();
+      const importStatus = isSuccess ? SecretSyncStatus.Succeeded : SecretSyncStatus.Failed;
+
+      await auditLogService.createAuditLog({
+        projectId: secretSync.projectId,
+        ...(auditLogInfo ?? {
+          actor: {
+            type: ActorType.PLATFORM,
+            metadata: {}
+          }
+        }),
+        event: {
+          type: EventType.SECRET_SYNC_IMPORT_SECRETS,
+          metadata: {
+            syncId: secretSync.id,
+            syncOptions: secretSync.syncOptions,
+            destination: secretSync.destination,
+            destinationConfig: secretSync.destinationConfig,
+            folderId: secretSync.folderId,
+            connectionId: secretSync.connectionId,
+            jobRanAt: ranAt,
+            jobId: job.id!,
+            importStatus,
+            importMessage,
+            importBehavior
+          }
+        }
+      });
+
+      if (isSuccess || isFinalAttempt) {
+        const updatedSecretSync = await secretSyncDAL.updateById(secretSync.id, {
+          importStatus,
+          lastImportJobId: job.id,
+          lastImportMessage: importMessage,
+          lastImportedAt: isSuccess ? ranAt : undefined
+        });
+
+        if (!isSuccess) {
+          await $queueSendSecretSyncFailedNotifications({
+            secretSync: updatedSecretSync,
+            action: SecretSyncAction.ImportSecrets,
+            auditLogInfo
+          });
+        }
+      }
+    }
+
+    logger.info("SecretSync Import Job with ID %s Completed", job.id);
+  };
+
+  const $handleRemoveSecretsJob = async (job: TSecretSyncRemoveSecretsDTO) => {
+    const {
+      data: { syncId, auditLogInfo, deleteSyncOnComplete }
+    } = job;
+
+    const secretSync = await secretSyncDAL.findById(syncId);
+
+    if (!secretSync) throw new Error(`Cannot find secret sync with ID ${syncId}`);
+
+    await secretSyncDAL.updateById(syncId, {
+      removeStatus: SecretSyncStatus.Running
+    });
+
+    logger.info(
+      `SecretSync Remove [syncId=${secretSync.id}] [destination=${secretSync.destination}] [projectId=${secretSync.projectId}] [folderId=${secretSync.folderId}] [connectionId=${secretSync.connectionId}]`
+    );
+
+    let isSuccess = false;
+    let removeMessage: string | null = null;
+    const isFinalAttempt = job.attemptsStarted === job.opts.attempts;
+
+    try {
+      const {
+        connection: { orgId, encryptedCredentials }
+      } = secretSync;
+
+      const credentials = await decryptAppConnectionCredentials({
+        orgId,
+        encryptedCredentials,
+        kmsService
+      });
+
+      const secretMap = await $getInfisicalSecrets(secretSync);
+
+      await SecretSyncFns.removeSecrets(
+        {
+          ...secretSync,
+          connection: {
+            ...secretSync.connection,
+            credentials
+          }
+        } as TSecretSyncWithCredentials,
+        secretMap
+      );
+
+      isSuccess = true;
+    } catch (err) {
+      logger.error(
+        err,
+        `SecretSync Remove Error [syncId=${secretSync.id}] [destination=${secretSync.destination}] [projectId=${secretSync.projectId}] [folderId=${secretSync.folderId}] [connectionId=${secretSync.connectionId}]`
+      );
+
+      if (appCfg.OTEL_TELEMETRY_COLLECTION_ENABLED) {
+        removeSecretsErrorHistogram.record(1, {
+          version: 1,
+          destination: secretSync.destination,
+          syncId: secretSync.id,
+          projectId: secretSync.projectId,
+          type: err instanceof AxiosError ? "AxiosError" : err?.constructor?.name || "UnknownError",
+          status: err instanceof AxiosError ? err.response?.status : undefined,
+          name: err instanceof Error ? err.name : undefined
+        });
+      }
+
+      removeMessage = parseSyncErrorMessage(err);
+
+      // re-throw so job fails
+      throw err;
+    } finally {
+      const ranAt = new Date();
+      const removeStatus = isSuccess ? SecretSyncStatus.Succeeded : SecretSyncStatus.Failed;
+
+      await auditLogService.createAuditLog({
+        projectId: secretSync.projectId,
+        ...(auditLogInfo ?? {
+          actor: {
+            type: ActorType.PLATFORM,
+            metadata: {}
+          }
+        }),
+        event: {
+          type: EventType.SECRET_SYNC_REMOVE_SECRETS,
+          metadata: {
+            syncId: secretSync.id,
+            syncOptions: secretSync.syncOptions,
+            destination: secretSync.destination,
+            destinationConfig: secretSync.destinationConfig,
+            folderId: secretSync.folderId,
+            connectionId: secretSync.connectionId,
+            jobRanAt: ranAt,
+            jobId: job.id!,
+            removeStatus,
+            removeMessage
+          }
+        }
+      });
+
+      if (isSuccess || isFinalAttempt) {
+        if (isSuccess && deleteSyncOnComplete) {
+          await secretSyncDAL.deleteById(secretSync.id);
+        } else {
+          const updatedSecretSync = await secretSyncDAL.updateById(secretSync.id, {
+            removeStatus,
+            lastRemoveJobId: job.id,
+            lastRemoveMessage: removeMessage,
+            lastRemovedAt: isSuccess ? ranAt : undefined
+          });
+
+          if (!isSuccess) {
+            await $queueSendSecretSyncFailedNotifications({
+              secretSync: updatedSecretSync,
+              action: SecretSyncAction.RemoveSecrets,
+              auditLogInfo
+            });
+          }
+        }
+      }
+    }
+
+    logger.info("SecretSync Remove Job with ID %s Completed", job.id);
+  };
+
+  const $sendSecretSyncFailedNotifications = async (job: TSendSecretSyncFailedNotificationsJobDTO) => {
+    const {
+      data: { secretSync, auditLogInfo, action }
+    } = job;
+
+    const { projectId, destination, name, folder, lastSyncMessage, lastRemoveMessage, lastImportMessage, environment } =
+      secretSync;
+
+    const projectMembers = await projectMembershipDAL.findAllProjectMembers(projectId);
+    const project = await projectDAL.findById(projectId);
+
+    let projectAdmins = projectMembers.filter((member) =>
+      member.roles.some((role) => role.role === ProjectMembershipRole.Admin)
+    );
+
+    const triggeredByUserId =
+      auditLogInfo && auditLogInfo.actor.type === ActorType.USER && auditLogInfo.actor.metadata.userId;
+
+    // only notify triggering user if triggered by admin
+    if (triggeredByUserId && projectAdmins.map((admin) => admin.userId).includes(triggeredByUserId)) {
+      projectAdmins = projectAdmins.filter((admin) => admin.userId === triggeredByUserId);
+    }
+
+    const syncDestination = SECRET_SYNC_NAME_MAP[destination as SecretSync];
+
+    let actionLabel: string;
+    let failureMessage: string | null | undefined;
+
+    switch (action) {
+      case SecretSyncAction.ImportSecrets:
+        actionLabel = "Import";
+        failureMessage = lastImportMessage;
+
+        break;
+      case SecretSyncAction.RemoveSecrets:
+        actionLabel = "Remove";
+        failureMessage = lastRemoveMessage;
+
+        break;
+      case SecretSyncAction.SyncSecrets:
+      default:
+        actionLabel = `Sync`;
+        failureMessage = lastSyncMessage;
+        break;
+    }
+
+    await smtpService.sendMail({
+      recipients: projectAdmins.map((member) => member.user.email!).filter(Boolean),
+      template: SmtpTemplates.SecretSyncFailed,
+      subjectLine: `Secret Sync Failed to ${actionLabel} Secrets`,
+      substitutions: {
+        syncName: name,
+        syncDestination,
+        content: `Your ${syncDestination} Sync named "${name}" failed while attempting to ${action.toLowerCase()} secrets.`,
+        failureMessage,
+        secretPath: folder?.path,
+        environment: environment?.name,
+        projectName: project.name,
+        syncUrl: `${appCfg.SITE_URL}/integrations/secret-syncs/${destination}/${secretSync.id}`
+      }
+    });
+  };
+
+  const queueSecretSyncsSyncSecretsByPath = async ({
+    secretPath,
+    projectId,
+    environmentSlug
+  }: TQueueSecretSyncsByPathDTO) => {
+    const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, secretPath);
+
+    if (!folder)
+      throw new Error(
+        `Could not find folder at path "${secretPath}" for environment with slug "${environmentSlug}" in project with ID "${projectId}"`
+      );
+
+    const secretSyncs = await secretSyncDAL.find({ folderId: folder.id, isAutoSyncEnabled: true });
+
+    await Promise.all(secretSyncs.map((secretSync) => queueSecretSyncSyncSecretsById({ syncId: secretSync.id })));
+  };
+
+  const $handleAcquireLockFailure = async (job: SecretSyncActionJob) => {
+    const { syncId, auditLogInfo } = job.data;
+
+    switch (job.name) {
+      case QueueJobs.SecretSyncSyncSecrets: {
+        const { failedToAcquireLockCount = 0, ...rest } = job.data as TQueueSecretSyncSyncSecretsByIdDTO;
+
+        if (failedToAcquireLockCount < 10) {
+          await queueSecretSyncSyncSecretsById({ ...rest, failedToAcquireLockCount: failedToAcquireLockCount + 1 });
+          return;
+        }
+
+        const secretSync = await secretSyncDAL.updateById(syncId, {
+          syncStatus: SecretSyncStatus.Failed,
+          lastSyncMessage:
+            "Failed to run job. This typically happens when a sync is already in progress. Please try again.",
+          lastSyncJobId: job.id
+        });
+
+        await $queueSendSecretSyncFailedNotifications({
+          secretSync,
+          action: SecretSyncAction.SyncSecrets,
+          auditLogInfo
+        });
+
+        break;
+      }
+      // Scott: the two cases below are unlikely to happen as we check the lock at the API level but including this as a fallback
+      case QueueJobs.SecretSyncImportSecrets: {
+        const secretSync = await secretSyncDAL.updateById(syncId, {
+          importStatus: SecretSyncStatus.Failed,
+          lastImportMessage:
+            "Failed to run job. This typically happens when a sync is already in progress. Please try again.",
+          lastImportJobId: job.id
+        });
+
+        await $queueSendSecretSyncFailedNotifications({
+          secretSync,
+          action: SecretSyncAction.ImportSecrets,
+          auditLogInfo
+        });
+
+        break;
+      }
+      case QueueJobs.SecretSyncRemoveSecrets: {
+        const secretSync = await secretSyncDAL.updateById(syncId, {
+          removeStatus: SecretSyncStatus.Failed,
+          lastRemoveMessage:
+            "Failed to run job. This typically happens when a sync is already in progress. Please try again.",
+          lastRemoveJobId: job.id
+        });
+
+        await $queueSendSecretSyncFailedNotifications({
+          secretSync,
+          action: SecretSyncAction.RemoveSecrets,
+          auditLogInfo
+        });
+
+        break;
+      }
+      default:
+        // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+        throw new Error(`Unhandled Secret Sync Job ${job.name}`);
+    }
+  };
+
+  queueService.start(QueueName.AppConnectionSecretSync, async (job) => {
+    if (job.name === QueueJobs.SecretSyncSendActionFailedNotifications) {
+      await $sendSecretSyncFailedNotifications(job as TSendSecretSyncFailedNotificationsJobDTO);
+      return;
+    }
+
+    const { syncId } = job.data as
+      | TQueueSecretSyncSyncSecretsByIdDTO
+      | TQueueSecretSyncImportSecretsByIdDTO
+      | TQueueSecretSyncRemoveSecretsByIdDTO;
+
+    let lock: Awaited<ReturnType<typeof keyStore.acquireLock>>;
+
+    try {
+      lock = await keyStore.acquireLock(
+        [KeyStorePrefixes.SecretSyncLock(syncId)],
+        // scott: not sure on this duration; syncs can take excessive amounts of time so we need to keep it locked,
+        // but should always release below...
+        5 * 60 * 1000
+      );
+    } catch (e) {
+      logger.info(`SecretSync Failed to acquire lock [syncId=${syncId}] [job=${job.name}]`);
+
+      await $handleAcquireLockFailure(job as SecretSyncActionJob);
+
+      return;
+    }
+
+    try {
+      switch (job.name) {
+        case QueueJobs.SecretSyncSyncSecrets:
+          await $handleSyncSecretsJob(job as TSecretSyncSyncSecretsDTO);
+          break;
+        case QueueJobs.SecretSyncImportSecrets:
+          await $handleImportSecretsJob(job as TSecretSyncImportSecretsDTO);
+          break;
+        case QueueJobs.SecretSyncRemoveSecrets:
+          await $handleRemoveSecretsJob(job as TSecretSyncRemoveSecretsDTO);
+          break;
+        default:
+          // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+          throw new Error(`Unhandled Secret Sync Job ${job.name}`);
+      }
+    } finally {
+      await lock.release();
+    }
+  });
+
+  return {
+    queueSecretSyncSyncSecretsById,
+    queueSecretSyncImportSecretsById,
+    queueSecretSyncRemoveSecretsById,
+    queueSecretSyncsSyncSecretsByPath
+  };
+};
diff --git a/backend/src/services/secret-sync/secret-sync-schemas.ts b/backend/src/services/secret-sync/secret-sync-schemas.ts
new file mode 100644
index 0000000000..9821c4e1d5
--- /dev/null
+++ b/backend/src/services/secret-sync/secret-sync-schemas.ts
@@ -0,0 +1,96 @@
+import { z } from "zod";
+
+import { SecretSyncsSchema } from "@app/db/schemas/secret-syncs";
+import { SecretSyncs } from "@app/lib/api-docs";
+import { removeTrailingSlash } from "@app/lib/fn";
+import { slugSchema } from "@app/server/lib/schemas";
+import { SecretSync, SecretSyncInitialSyncBehavior } from "@app/services/secret-sync/secret-sync-enums";
+import { SECRET_SYNC_CONNECTION_MAP } from "@app/services/secret-sync/secret-sync-maps";
+import { TSyncOptionsConfig } from "@app/services/secret-sync/secret-sync-types";
+
+const SyncOptionsSchema = (secretSync: SecretSync, options: TSyncOptionsConfig = { canImportSecrets: true }) =>
+  z.object({
+    initialSyncBehavior: (options.canImportSecrets
+      ? z.nativeEnum(SecretSyncInitialSyncBehavior)
+      : z.literal(SecretSyncInitialSyncBehavior.OverwriteDestination)
+    ).describe(SecretSyncs.SYNC_OPTIONS(secretSync).INITIAL_SYNC_BEHAVIOR)
+    // prependPrefix: z
+    //   .string()
+    //   .trim()
+    //   .transform((str) => str.toUpperCase())
+    //   .optional()
+    //   .describe(SecretSyncs.SYNC_OPTIONS(secretSync).PREPEND_PREFIX),
+    // appendSuffix: z
+    //   .string()
+    //   .trim()
+    //   .transform((str) => str.toUpperCase())
+    //   .optional()
+    //   .describe(SecretSyncs.SYNC_OPTIONS(secretSync).APPEND_SUFFIX)
+  });
+
+export const BaseSecretSyncSchema = (destination: SecretSync, syncOptionsConfig?: TSyncOptionsConfig) =>
+  SecretSyncsSchema.omit({
+    destination: true,
+    destinationConfig: true,
+    syncOptions: true
+  }).extend({
+    // destination needs to be on the extended object for type differentiation
+    syncOptions: SyncOptionsSchema(destination, syncOptionsConfig),
+    // join properties
+    projectId: z.string(),
+    connection: z.object({
+      app: z.literal(SECRET_SYNC_CONNECTION_MAP[destination]),
+      name: z.string(),
+      id: z.string().uuid()
+    }),
+    environment: z.object({ slug: z.string(), name: z.string(), id: z.string().uuid() }).nullable(),
+    folder: z.object({ id: z.string(), path: z.string() }).nullable()
+  });
+
+export const GenericCreateSecretSyncFieldsSchema = (destination: SecretSync, syncOptionsConfig?: TSyncOptionsConfig) =>
+  z.object({
+    name: slugSchema({ field: "name" }).describe(SecretSyncs.CREATE(destination).name),
+    projectId: z.string().trim().min(1, "Project ID required").describe(SecretSyncs.CREATE(destination).projectId),
+    description: z
+      .string()
+      .trim()
+      .max(256, "Description cannot exceed 256 characters")
+      .nullish()
+      .describe(SecretSyncs.CREATE(destination).description),
+    connectionId: z.string().uuid().describe(SecretSyncs.CREATE(destination).connectionId),
+    environment: slugSchema({ field: "environment", max: 64 }).describe(SecretSyncs.CREATE(destination).environment),
+    secretPath: z
+      .string()
+      .trim()
+      .min(1, "Secret path required")
+      .transform(removeTrailingSlash)
+      .describe(SecretSyncs.CREATE(destination).secretPath),
+    isAutoSyncEnabled: z.boolean().default(true).describe(SecretSyncs.CREATE(destination).isAutoSyncEnabled),
+    syncOptions: SyncOptionsSchema(destination, syncOptionsConfig).describe(SecretSyncs.CREATE(destination).syncOptions)
+  });
+
+export const GenericUpdateSecretSyncFieldsSchema = (destination: SecretSync, syncOptionsConfig?: TSyncOptionsConfig) =>
+  z.object({
+    name: slugSchema({ field: "name" }).describe(SecretSyncs.UPDATE(destination).name).optional(),
+    connectionId: z.string().uuid().describe(SecretSyncs.UPDATE(destination).connectionId).optional(),
+    description: z
+      .string()
+      .trim()
+      .max(256, "Description cannot exceed 256 characters")
+      .nullish()
+      .describe(SecretSyncs.UPDATE(destination).description),
+    environment: slugSchema({ field: "environment", max: 64 })
+      .optional()
+      .describe(SecretSyncs.UPDATE(destination).environment),
+    secretPath: z
+      .string()
+      .trim()
+      .min(1, "Invalid secret path")
+      .transform(removeTrailingSlash)
+      .optional()
+      .describe(SecretSyncs.UPDATE(destination).secretPath),
+    isAutoSyncEnabled: z.boolean().optional().describe(SecretSyncs.UPDATE(destination).isAutoSyncEnabled),
+    syncOptions: SyncOptionsSchema(destination, syncOptionsConfig)
+      .optional()
+      .describe(SecretSyncs.UPDATE(destination).syncOptions)
+  });
diff --git a/backend/src/services/secret-sync/secret-sync-service.ts b/backend/src/services/secret-sync/secret-sync-service.ts
new file mode 100644
index 0000000000..4ce2fd2d55
--- /dev/null
+++ b/backend/src/services/secret-sync/secret-sync-service.ts
@@ -0,0 +1,562 @@
+import { ForbiddenError, subject } from "@casl/ability";
+
+import { ActionProjectType } from "@app/db/schemas";
+import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
+import {
+  ProjectPermissionActions,
+  ProjectPermissionSecretSyncActions,
+  ProjectPermissionSub
+} from "@app/ee/services/permission/project-permission";
+import { KeyStorePrefixes, TKeyStoreFactory } from "@app/keystore/keystore";
+import { BadRequestError, NotFoundError } from "@app/lib/errors";
+import { OrgServiceActor } from "@app/lib/types";
+import { TAppConnectionServiceFactory } from "@app/services/app-connection/app-connection-service";
+import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
+import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
+import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
+import { listSecretSyncOptions } from "@app/services/secret-sync/secret-sync-fns";
+import {
+  SecretSyncStatus,
+  TCreateSecretSyncDTO,
+  TDeleteSecretSyncDTO,
+  TFindSecretSyncByIdDTO,
+  TFindSecretSyncByNameDTO,
+  TListSecretSyncsByProjectId,
+  TSecretSync,
+  TTriggerSecretSyncImportSecretsByIdDTO,
+  TTriggerSecretSyncRemoveSecretsByIdDTO,
+  TTriggerSecretSyncSyncSecretsByIdDTO,
+  TUpdateSecretSyncDTO
+} from "@app/services/secret-sync/secret-sync-types";
+
+import { TSecretSyncDALFactory } from "./secret-sync-dal";
+import { SECRET_SYNC_CONNECTION_MAP, SECRET_SYNC_NAME_MAP } from "./secret-sync-maps";
+import { TSecretSyncQueueFactory } from "./secret-sync-queue";
+
+type TSecretSyncServiceFactoryDep = {
+  secretSyncDAL: TSecretSyncDALFactory;
+  appConnectionService: Pick<TAppConnectionServiceFactory, "connectAppConnectionById">;
+  permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getOrgPermission">;
+  projectBotService: Pick<TProjectBotServiceFactory, "getBotKey">;
+  folderDAL: Pick<TSecretFolderDALFactory, "findByProjectId" | "findById" | "findBySecretPath">;
+  keyStore: Pick<TKeyStoreFactory, "getItem">;
+  secretSyncQueue: Pick<
+    TSecretSyncQueueFactory,
+    "queueSecretSyncSyncSecretsById" | "queueSecretSyncImportSecretsById" | "queueSecretSyncRemoveSecretsById"
+  >;
+};
+
+export type TSecretSyncServiceFactory = ReturnType<typeof secretSyncServiceFactory>;
+
+export const secretSyncServiceFactory = ({
+  secretSyncDAL,
+  folderDAL,
+  permissionService,
+  appConnectionService,
+  projectBotService,
+  secretSyncQueue,
+  keyStore
+}: TSecretSyncServiceFactoryDep) => {
+  const listSecretSyncsByProjectId = async (
+    { projectId, destination }: TListSecretSyncsByProjectId,
+    actor: OrgServiceActor
+  ) => {
+    const { permission } = await permissionService.getProjectPermission({
+      actor: actor.type,
+      actorId: actor.id,
+      actorAuthMethod: actor.authMethod,
+      actorOrgId: actor.orgId,
+      actionProjectType: ActionProjectType.SecretManager,
+      projectId
+    });
+
+    ForbiddenError.from(permission).throwUnlessCan(
+      ProjectPermissionSecretSyncActions.Read,
+      ProjectPermissionSub.SecretSyncs
+    );
+
+    const secretSyncs = await secretSyncDAL.find({
+      ...(destination && { destination }),
+      projectId
+    });
+
+    return secretSyncs as TSecretSync[];
+  };
+
+  const findSecretSyncById = async ({ destination, syncId }: TFindSecretSyncByIdDTO, actor: OrgServiceActor) => {
+    const secretSync = await secretSyncDAL.findById(syncId);
+
+    if (!secretSync)
+      throw new NotFoundError({
+        message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
+      });
+
+    const { permission } = await permissionService.getProjectPermission({
+      actor: actor.type,
+      actorId: actor.id,
+      actorAuthMethod: actor.authMethod,
+      actorOrgId: actor.orgId,
+      actionProjectType: ActionProjectType.SecretManager,
+      projectId: secretSync.projectId
+    });
+
+    ForbiddenError.from(permission).throwUnlessCan(
+      ProjectPermissionSecretSyncActions.Read,
+      ProjectPermissionSub.SecretSyncs
+    );
+
+    if (secretSync.connection.app !== SECRET_SYNC_CONNECTION_MAP[destination])
+      throw new BadRequestError({
+        message: `Secret sync with ID "${secretSync.id}" is not configured for ${SECRET_SYNC_NAME_MAP[destination]}`
+      });
+
+    return secretSync as TSecretSync;
+  };
+
+  const findSecretSyncByName = async (
+    { destination, syncName, projectId }: TFindSecretSyncByNameDTO,
+    actor: OrgServiceActor
+  ) => {
+    const folders = await folderDAL.findByProjectId(projectId);
+
+    // we prevent conflicting names within a project so this will only return one at most
+    const [secretSync] = await secretSyncDAL.find({
+      name: syncName,
+      $in: {
+        folderId: folders.map((folder) => folder.id)
+      }
+    });
+
+    if (!secretSync)
+      throw new NotFoundError({
+        message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with name "${syncName}"`
+      });
+
+    const { permission } = await permissionService.getProjectPermission({
+      actor: actor.type,
+      actorId: actor.id,
+      actorAuthMethod: actor.authMethod,
+      actorOrgId: actor.orgId,
+      actionProjectType: ActionProjectType.SecretManager,
+      projectId: secretSync.projectId
+    });
+
+    ForbiddenError.from(permission).throwUnlessCan(
+      ProjectPermissionSecretSyncActions.Read,
+      ProjectPermissionSub.SecretSyncs
+    );
+
+    if (secretSync.connection.app !== SECRET_SYNC_CONNECTION_MAP[destination])
+      throw new BadRequestError({
+        message: `Secret sync with ID "${secretSync.id}" is not configured for ${SECRET_SYNC_NAME_MAP[destination]}`
+      });
+
+    return secretSync as TSecretSync;
+  };
+
+  const createSecretSync = async (
+    { projectId, secretPath, environment, ...params }: TCreateSecretSyncDTO,
+    actor: OrgServiceActor
+  ) => {
+    const { permission: projectPermission } = await permissionService.getProjectPermission({
+      actor: actor.type,
+      actorId: actor.id,
+      actorAuthMethod: actor.authMethod,
+      actorOrgId: actor.orgId,
+      actionProjectType: ActionProjectType.SecretManager,
+      projectId
+    });
+
+    const { shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId);
+
+    if (!shouldUseSecretV2Bridge)
+      throw new BadRequestError({ message: "Project version does not support Secret Syncs" });
+
+    ForbiddenError.from(projectPermission).throwUnlessCan(
+      ProjectPermissionSecretSyncActions.Create,
+      ProjectPermissionSub.SecretSyncs
+    );
+
+    ForbiddenError.from(projectPermission).throwUnlessCan(
+      ProjectPermissionActions.Read,
+      subject(ProjectPermissionSub.Secrets, {
+        environment,
+        secretPath
+      })
+    );
+
+    const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
+
+    if (!folder)
+      throw new BadRequestError({
+        message: `Could not find folder with path "${secretPath}" in environment "${environment}" for project with ID "${projectId}"`
+      });
+
+    const destinationApp = SECRET_SYNC_CONNECTION_MAP[params.destination];
+
+    // validates permission to connect and app is valid for sync destination
+    await appConnectionService.connectAppConnectionById(destinationApp, params.connectionId, actor);
+
+    const secretSync = await secretSyncDAL.transaction(async (tx) => {
+      const isConflictingName = Boolean(
+        (
+          await secretSyncDAL.find(
+            {
+              name: params.name,
+              projectId
+            },
+            tx
+          )
+        ).length
+      );
+
+      if (isConflictingName)
+        throw new BadRequestError({
+          message: `A Secret Sync with the name "${params.name}" already exists for the project with ID "${folder.projectId}"`
+        });
+
+      const sync = await secretSyncDAL.create({
+        folderId: folder.id,
+        ...params,
+        ...(params.isAutoSyncEnabled && { syncStatus: SecretSyncStatus.Pending }),
+        projectId
+      });
+
+      return sync;
+    });
+
+    if (secretSync.isAutoSyncEnabled) await secretSyncQueue.queueSecretSyncSyncSecretsById({ syncId: secretSync.id });
+
+    return secretSync as TSecretSync;
+  };
+
+  const updateSecretSync = async (
+    { destination, syncId, secretPath, environment, ...params }: TUpdateSecretSyncDTO,
+    actor: OrgServiceActor
+  ) => {
+    const secretSync = await secretSyncDAL.findById(syncId);
+
+    if (!secretSync)
+      throw new NotFoundError({
+        message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID ${syncId}`
+      });
+
+    const { permission } = await permissionService.getProjectPermission({
+      actor: actor.type,
+      actorId: actor.id,
+      actorAuthMethod: actor.authMethod,
+      actorOrgId: actor.orgId,
+      actionProjectType: ActionProjectType.SecretManager,
+      projectId: secretSync.projectId
+    });
+
+    ForbiddenError.from(permission).throwUnlessCan(
+      ProjectPermissionSecretSyncActions.Edit,
+      ProjectPermissionSub.SecretSyncs
+    );
+
+    if (secretSync.connection.app !== SECRET_SYNC_CONNECTION_MAP[destination])
+      throw new BadRequestError({
+        message: `Secret sync with ID "${secretSync.id}" is not configured for ${SECRET_SYNC_NAME_MAP[destination]}`
+      });
+
+    const updatedSecretSync = await secretSyncDAL.transaction(async (tx) => {
+      let { folderId } = secretSync;
+
+      if (params.connectionId) {
+        const destinationApp = SECRET_SYNC_CONNECTION_MAP[secretSync.destination as SecretSync];
+
+        // validates permission to connect and app is valid for sync destination
+        await appConnectionService.connectAppConnectionById(destinationApp, params.connectionId, actor);
+      }
+
+      if (
+        (secretPath && secretPath !== secretSync.folder?.path) ||
+        (environment && environment !== secretSync.environment?.slug)
+      ) {
+        const updatedEnvironment = environment ?? secretSync.environment?.slug;
+        const updatedSecretPath = secretPath ?? secretSync.folder?.path;
+
+        if (!updatedEnvironment || !updatedSecretPath)
+          throw new BadRequestError({ message: "Must specify both source environment and secret path" });
+
+        ForbiddenError.from(permission).throwUnlessCan(
+          ProjectPermissionActions.Read,
+          subject(ProjectPermissionSub.Secrets, {
+            environment: updatedEnvironment,
+            secretPath: updatedSecretPath
+          })
+        );
+
+        const newFolder = await folderDAL.findBySecretPath(secretSync.projectId, updatedEnvironment, updatedSecretPath);
+
+        if (!newFolder)
+          throw new BadRequestError({
+            message: `Could not find folder with path "${secretPath}" in environment "${environment}" for project with ID "${secretSync.projectId}"`
+          });
+
+        folderId = newFolder.id;
+      }
+
+      if (params.name && secretSync.name !== params.name) {
+        const isConflictingName = Boolean(
+          (
+            await secretSyncDAL.find(
+              {
+                name: params.name,
+                projectId: secretSync.projectId
+              },
+              tx
+            )
+          ).length
+        );
+
+        if (isConflictingName)
+          throw new BadRequestError({
+            message: `A Secret Sync with the name "${params.name}" already exists for project with ID "${secretSync.projectId}"`
+          });
+      }
+
+      const isAutoSyncEnabled = params.isAutoSyncEnabled ?? secretSync.isAutoSyncEnabled;
+
+      const updatedSync = await secretSyncDAL.updateById(syncId, {
+        ...params,
+        ...(isAutoSyncEnabled && folderId && { syncStatus: SecretSyncStatus.Pending }),
+        folderId
+      });
+
+      return updatedSync;
+    });
+
+    if (updatedSecretSync.isAutoSyncEnabled)
+      await secretSyncQueue.queueSecretSyncSyncSecretsById({ syncId: secretSync.id });
+
+    return updatedSecretSync as TSecretSync;
+  };
+
+  const deleteSecretSync = async (
+    { destination, syncId, removeSecrets }: TDeleteSecretSyncDTO,
+    actor: OrgServiceActor
+  ) => {
+    const secretSync = await secretSyncDAL.findById(syncId);
+
+    if (!secretSync)
+      throw new NotFoundError({
+        message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
+      });
+
+    const { permission } = await permissionService.getProjectPermission({
+      actor: actor.type,
+      actorId: actor.id,
+      actorAuthMethod: actor.authMethod,
+      actorOrgId: actor.orgId,
+      actionProjectType: ActionProjectType.SecretManager,
+      projectId: secretSync.projectId
+    });
+
+    ForbiddenError.from(permission).throwUnlessCan(
+      ProjectPermissionSecretSyncActions.Delete,
+      ProjectPermissionSub.SecretSyncs
+    );
+
+    if (secretSync.connection.app !== SECRET_SYNC_CONNECTION_MAP[destination])
+      throw new BadRequestError({
+        message: `Secret sync with ID "${secretSync.id}" is not configured for ${SECRET_SYNC_NAME_MAP[destination]}`
+      });
+
+    if (removeSecrets) {
+      ForbiddenError.from(permission).throwUnlessCan(
+        ProjectPermissionSecretSyncActions.RemoveSecrets,
+        ProjectPermissionSub.SecretSyncs
+      );
+
+      if (!secretSync.folderId)
+        throw new BadRequestError({
+          message: `Invalid source configuration: folder no longer exists. Please configure a valid source and try again.`
+        });
+
+      const isSyncJobRunning = Boolean(await keyStore.getItem(KeyStorePrefixes.SecretSyncLock(syncId)));
+
+      if (isSyncJobRunning)
+        throw new BadRequestError({ message: `A job for this sync is already in progress. Please try again shortly.` });
+
+      await secretSyncQueue.queueSecretSyncRemoveSecretsById({ syncId, deleteSyncOnComplete: true });
+
+      const updatedSecretSync = await secretSyncDAL.updateById(syncId, {
+        removeStatus: SecretSyncStatus.Pending
+      });
+
+      return updatedSecretSync;
+    }
+
+    await secretSyncDAL.deleteById(syncId);
+
+    return secretSync as TSecretSync;
+  };
+
+  const triggerSecretSyncSyncSecretsById = async (
+    { syncId, destination, ...params }: TTriggerSecretSyncSyncSecretsByIdDTO,
+    actor: OrgServiceActor
+  ) => {
+    const secretSync = await secretSyncDAL.findById(syncId);
+
+    if (!secretSync)
+      throw new NotFoundError({
+        message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
+      });
+
+    const { permission } = await permissionService.getProjectPermission({
+      actor: actor.type,
+      actorId: actor.id,
+      actorAuthMethod: actor.authMethod,
+      actorOrgId: actor.orgId,
+      actionProjectType: ActionProjectType.SecretManager,
+      projectId: secretSync.projectId
+    });
+
+    ForbiddenError.from(permission).throwUnlessCan(
+      ProjectPermissionSecretSyncActions.SyncSecrets,
+      ProjectPermissionSub.SecretSyncs
+    );
+
+    if (secretSync.connection.app !== SECRET_SYNC_CONNECTION_MAP[destination])
+      throw new BadRequestError({
+        message: `Secret sync with ID "${secretSync.id}" is not configured for ${SECRET_SYNC_NAME_MAP[destination]}`
+      });
+
+    if (!secretSync.folderId)
+      throw new BadRequestError({
+        message: `Invalid source configuration: folder no longer exists. Please configure a valid source and try again.`
+      });
+
+    const isSyncJobRunning = Boolean(await keyStore.getItem(KeyStorePrefixes.SecretSyncLock(syncId)));
+
+    if (isSyncJobRunning)
+      throw new BadRequestError({ message: `A job for this sync is already in progress. Please try again shortly.` });
+
+    await secretSyncQueue.queueSecretSyncSyncSecretsById({ syncId, ...params });
+
+    const updatedSecretSync = await secretSyncDAL.updateById(syncId, {
+      syncStatus: SecretSyncStatus.Pending
+    });
+
+    return updatedSecretSync as TSecretSync;
+  };
+
+  const triggerSecretSyncImportSecretsById = async (
+    { syncId, destination, ...params }: TTriggerSecretSyncImportSecretsByIdDTO,
+    actor: OrgServiceActor
+  ) => {
+    if (!listSecretSyncOptions().find((option) => option.destination === destination)?.canImportSecrets) {
+      throw new BadRequestError({
+        message: `${SECRET_SYNC_NAME_MAP[destination]} does not support importing secrets.`
+      });
+    }
+
+    const secretSync = await secretSyncDAL.findById(syncId);
+
+    if (!secretSync)
+      throw new NotFoundError({
+        message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
+      });
+
+    const { permission } = await permissionService.getProjectPermission({
+      actor: actor.type,
+      actorId: actor.id,
+      actorAuthMethod: actor.authMethod,
+      actorOrgId: actor.orgId,
+      actionProjectType: ActionProjectType.SecretManager,
+      projectId: secretSync.projectId
+    });
+
+    ForbiddenError.from(permission).throwUnlessCan(
+      ProjectPermissionSecretSyncActions.ImportSecrets,
+      ProjectPermissionSub.SecretSyncs
+    );
+
+    if (secretSync.connection.app !== SECRET_SYNC_CONNECTION_MAP[destination])
+      throw new BadRequestError({
+        message: `Secret sync with ID "${secretSync.id}" is not configured for ${SECRET_SYNC_NAME_MAP[destination]}`
+      });
+
+    if (!secretSync.folderId)
+      throw new BadRequestError({
+        message: `Invalid source configuration: folder no longer exists. Please configure a valid source and try again.`
+      });
+
+    const isSyncJobRunning = Boolean(await keyStore.getItem(KeyStorePrefixes.SecretSyncLock(syncId)));
+
+    if (isSyncJobRunning)
+      throw new BadRequestError({ message: `A job for this sync is already in progress. Please try again shortly.` });
+
+    await secretSyncQueue.queueSecretSyncImportSecretsById({ syncId, ...params });
+
+    const updatedSecretSync = await secretSyncDAL.updateById(syncId, {
+      importStatus: SecretSyncStatus.Pending
+    });
+
+    return updatedSecretSync as TSecretSync;
+  };
+
+  const triggerSecretSyncRemoveSecretsById = async (
+    { syncId, destination, ...params }: TTriggerSecretSyncRemoveSecretsByIdDTO,
+    actor: OrgServiceActor
+  ) => {
+    const secretSync = await secretSyncDAL.findById(syncId);
+
+    if (!secretSync)
+      throw new NotFoundError({
+        message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
+      });
+
+    const { permission } = await permissionService.getProjectPermission({
+      actor: actor.type,
+      actorId: actor.id,
+      actorAuthMethod: actor.authMethod,
+      actorOrgId: actor.orgId,
+      actionProjectType: ActionProjectType.SecretManager,
+      projectId: secretSync.projectId
+    });
+
+    ForbiddenError.from(permission).throwUnlessCan(
+      ProjectPermissionSecretSyncActions.RemoveSecrets,
+      ProjectPermissionSub.SecretSyncs
+    );
+
+    if (secretSync.connection.app !== SECRET_SYNC_CONNECTION_MAP[destination])
+      throw new BadRequestError({
+        message: `Secret sync with ID "${secretSync.id}" is not configured for ${SECRET_SYNC_NAME_MAP[destination]}`
+      });
+
+    if (!secretSync.folderId)
+      throw new BadRequestError({
+        message: `Invalid source configuration: folder no longer exists. Please configure a valid source and try again.`
+      });
+
+    const isSyncJobRunning = Boolean(await keyStore.getItem(KeyStorePrefixes.SecretSyncLock(syncId)));
+
+    if (isSyncJobRunning)
+      throw new BadRequestError({ message: `A job for this sync is already in progress. Please try again shortly.` });
+
+    await secretSyncQueue.queueSecretSyncRemoveSecretsById({ syncId, ...params });
+
+    const updatedSecretSync = await secretSyncDAL.updateById(syncId, {
+      removeStatus: SecretSyncStatus.Pending
+    });
+
+    return updatedSecretSync as TSecretSync;
+  };
+
+  return {
+    listSecretSyncOptions,
+    listSecretSyncsByProjectId,
+    findSecretSyncById,
+    findSecretSyncByName,
+    createSecretSync,
+    updateSecretSync,
+    deleteSecretSync,
+    triggerSecretSyncSyncSecretsById,
+    triggerSecretSyncImportSecretsById,
+    triggerSecretSyncRemoveSecretsById
+  };
+};
diff --git a/backend/src/services/secret-sync/secret-sync-types.ts b/backend/src/services/secret-sync/secret-sync-types.ts
new file mode 100644
index 0000000000..eade6671dd
--- /dev/null
+++ b/backend/src/services/secret-sync/secret-sync-types.ts
@@ -0,0 +1,148 @@
+import { Job } from "bullmq";
+
+import { TCreateAuditLogDTO } from "@app/ee/services/audit-log/audit-log-types";
+import { QueueJobs } from "@app/queue";
+import {
+  TGitHubSync,
+  TGitHubSyncInput,
+  TGitHubSyncListItem,
+  TGitHubSyncWithCredentials
+} from "@app/services/secret-sync/github";
+import { TSecretSyncDALFactory } from "@app/services/secret-sync/secret-sync-dal";
+import { SecretSync, SecretSyncImportBehavior } from "@app/services/secret-sync/secret-sync-enums";
+
+import {
+  TAwsParameterStoreSync,
+  TAwsParameterStoreSyncInput,
+  TAwsParameterStoreSyncListItem,
+  TAwsParameterStoreSyncWithCredentials
+} from "./aws-parameter-store";
+
+export type TSecretSync = TAwsParameterStoreSync | TGitHubSync;
+
+export type TSecretSyncWithCredentials = TAwsParameterStoreSyncWithCredentials | TGitHubSyncWithCredentials;
+
+export type TSecretSyncInput = TAwsParameterStoreSyncInput | TGitHubSyncInput;
+
+export type TSecretSyncListItem = TAwsParameterStoreSyncListItem | TGitHubSyncListItem;
+
+export type TSyncOptionsConfig = {
+  canImportSecrets: boolean;
+};
+
+export type TListSecretSyncsByProjectId = {
+  projectId: string;
+  destination?: SecretSync;
+};
+
+export type TFindSecretSyncByIdDTO = {
+  syncId: string;
+  destination: SecretSync;
+};
+
+export type TFindSecretSyncByNameDTO = {
+  syncName: string;
+  projectId: string;
+  destination: SecretSync;
+};
+
+export type TCreateSecretSyncDTO = Pick<TSecretSync, "syncOptions" | "destinationConfig" | "name" | "connectionId"> & {
+  destination: SecretSync;
+  projectId: string;
+  secretPath: string;
+  environment: string;
+  isAutoSyncEnabled?: boolean;
+};
+
+export type TUpdateSecretSyncDTO = Partial<Omit<TCreateSecretSyncDTO, "projectId">> & {
+  syncId: string;
+  destination: SecretSync;
+};
+
+export type TDeleteSecretSyncDTO = {
+  destination: SecretSync;
+  syncId: string;
+  removeSecrets: boolean;
+};
+
+type AuditLogInfo = Pick<TCreateAuditLogDTO, "userAgent" | "userAgentType" | "ipAddress" | "actor">;
+
+export enum SecretSyncStatus {
+  Pending = "pending",
+  Running = "running",
+  Succeeded = "succeeded",
+  Failed = "failed"
+}
+
+export enum SecretSyncAction {
+  SyncSecrets = "sync-secrets",
+  ImportSecrets = "import-secrets",
+  RemoveSecrets = "remove-secrets"
+}
+
+export type TSecretSyncRaw = NonNullable<Awaited<ReturnType<TSecretSyncDALFactory["findById"]>>>;
+
+export type TQueueSecretSyncsByPathDTO = {
+  secretPath: string;
+  environmentSlug: string;
+  projectId: string;
+};
+
+export type TQueueSecretSyncSyncSecretsByIdDTO = {
+  syncId: string;
+  failedToAcquireLockCount?: number;
+  auditLogInfo?: AuditLogInfo;
+};
+
+export type TTriggerSecretSyncSyncSecretsByIdDTO = {
+  destination: SecretSync;
+} & TQueueSecretSyncSyncSecretsByIdDTO;
+
+export type TQueueSecretSyncImportSecretsByIdDTO = {
+  syncId: string;
+  importBehavior: SecretSyncImportBehavior;
+  auditLogInfo?: AuditLogInfo;
+};
+
+export type TTriggerSecretSyncImportSecretsByIdDTO = {
+  destination: SecretSync;
+} & TQueueSecretSyncImportSecretsByIdDTO;
+
+export type TQueueSecretSyncRemoveSecretsByIdDTO = {
+  syncId: string;
+  auditLogInfo?: AuditLogInfo;
+  deleteSyncOnComplete?: boolean;
+};
+
+export type TTriggerSecretSyncRemoveSecretsByIdDTO = {
+  destination: SecretSync;
+} & TQueueSecretSyncRemoveSecretsByIdDTO;
+
+export type TQueueSendSecretSyncActionFailedNotificationsDTO = {
+  secretSync: TSecretSyncRaw;
+  auditLogInfo?: AuditLogInfo;
+  action: SecretSyncAction;
+};
+
+export type TSecretSyncSyncSecretsDTO = Job<TQueueSecretSyncSyncSecretsByIdDTO, void, QueueJobs.SecretSyncSyncSecrets>;
+export type TSecretSyncImportSecretsDTO = Job<
+  TQueueSecretSyncImportSecretsByIdDTO,
+  void,
+  QueueJobs.SecretSyncSyncSecrets
+>;
+export type TSecretSyncRemoveSecretsDTO = Job<
+  TQueueSecretSyncRemoveSecretsByIdDTO,
+  void,
+  QueueJobs.SecretSyncSyncSecrets
+>;
+
+export type TSendSecretSyncFailedNotificationsJobDTO = Job<
+  TQueueSendSecretSyncActionFailedNotificationsDTO,
+  void,
+  QueueJobs.SecretSyncSendActionFailedNotifications
+>;
+
+export type TSecretMap = Record<
+  string,
+  { value: string; comment?: string; skipMultilineEncoding?: boolean | null | undefined }
+>;
diff --git a/backend/src/services/secret/secret-queue.ts b/backend/src/services/secret/secret-queue.ts
index 661da23628..dc973c0b1f 100644
--- a/backend/src/services/secret/secret-queue.ts
+++ b/backend/src/services/secret/secret-queue.ts
@@ -29,6 +29,7 @@ import { createManySecretsRawFnFactory, updateManySecretsRawFnFactory } from "@a
 import { TSecretVersionDALFactory } from "@app/services/secret/secret-version-dal";
 import { TSecretVersionTagDALFactory } from "@app/services/secret/secret-version-tag-dal";
 import { TSecretBlindIndexDALFactory } from "@app/services/secret-blind-index/secret-blind-index-dal";
+import { TSecretSyncQueueFactory } from "@app/services/secret-sync/secret-sync-queue";
 import { TSecretTagDALFactory } from "@app/services/secret-tag/secret-tag-dal";
 
 import { ActorType } from "../auth/auth-type";
@@ -107,6 +108,7 @@ type TSecretQueueFactoryDep = {
   orgService: Pick<TOrgServiceFactory, "addGhostUser">;
   projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "create">;
   resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
+  secretSyncQueue: Pick<TSecretSyncQueueFactory, "queueSecretSyncsSyncSecretsByPath">;
 };
 
 export type TGetSecrets = {
@@ -166,7 +168,8 @@ export const secretQueueFactory = ({
   orgService,
   projectUserMembershipRoleDAL,
   projectKeyDAL,
-  resourceMetadataDAL
+  resourceMetadataDAL,
+  secretSyncQueue
 }: TSecretQueueFactoryDep) => {
   const integrationMeter = opentelemetry.metrics.getMeter("Integrations");
   const errorHistogram = integrationMeter.createHistogram("integration_secret_sync_errors", {
@@ -633,6 +636,9 @@ export const secretQueueFactory = ({
         }
       }
     );
+
+    await secretSyncQueue.queueSecretSyncsSyncSecretsByPath({ projectId, environmentSlug: environment, secretPath });
+
     await syncIntegrations({ secretPath, projectId, environment, deDupeQueue, isManual: false });
     if (!excludeReplication) {
       await replicateSecrets({
diff --git a/backend/src/services/smtp/smtp-service.ts b/backend/src/services/smtp/smtp-service.ts
index a2ed85749d..d997d52f41 100644
--- a/backend/src/services/smtp/smtp-service.ts
+++ b/backend/src/services/smtp/smtp-service.ts
@@ -35,6 +35,7 @@ export enum SmtpTemplates {
   ScimUserProvisioned = "scimUserProvisioned.handlebars",
   PkiExpirationAlert = "pkiExpirationAlert.handlebars",
   IntegrationSyncFailed = "integrationSyncFailed.handlebars",
+  SecretSyncFailed = "secretSyncFailed.handlebars",
   ExternalImportSuccessful = "externalImportSuccessful.handlebars",
   ExternalImportFailed = "externalImportFailed.handlebars",
   ExternalImportStarted = "externalImportStarted.handlebars"
diff --git a/backend/src/services/smtp/templates/secretSyncFailed.handlebars b/backend/src/services/smtp/templates/secretSyncFailed.handlebars
new file mode 100644
index 0000000000..3e7ad7831d
--- /dev/null
+++ b/backend/src/services/smtp/templates/secretSyncFailed.handlebars
@@ -0,0 +1,39 @@
+<html>
+
+  <head>
+    <meta charset="utf-8" />
+    <meta http-equiv="x-ua-compatible" content="ie=edge" />
+    <title>{{syncDestination}} Sync "{{syncName}}" Failed</title>
+  </head>
+
+  <body>
+    <h2>Infisical</h2>
+
+    <div>
+      <p>{{content}}</p>
+      <a href="{{syncUrl}}">
+        View in Infisical.
+      </a>
+    </div>
+
+    <br />
+    <div>
+      <p><strong>Name</strong>: {{syncName}}</p>
+      <p><strong>Destination</strong>: {{syncDestination}}</p>
+      <p><strong>Project</strong>: {{projectName}}</p>
+      {{#if environment}}
+          <p><strong>Environment</strong>: {{environment}}</p>
+      {{/if}}
+      {{#if secretPath}}
+          <p><strong>Secret Path</strong>: {{secretPath}}</p>
+      {{/if}}
+    </div>
+
+    {{#if failureMessage}}
+      <p><b>Reason: </b>{{failureMessage}}</p>
+    {{/if}}
+
+    {{emailFooter}}
+  </body>
+
+</html>
\ No newline at end of file
diff --git a/docs/api-reference/endpoints/app-connections/aws/available.mdx b/docs/api-reference/endpoints/app-connections/aws/available.mdx
new file mode 100644
index 0000000000..1386c068d4
--- /dev/null
+++ b/docs/api-reference/endpoints/app-connections/aws/available.mdx
@@ -0,0 +1,4 @@
+---
+title: "Available"
+openapi: "GET /api/v1/app-connections/aws/available"
+---
diff --git a/docs/api-reference/endpoints/app-connections/aws/get-by-name.mdx b/docs/api-reference/endpoints/app-connections/aws/get-by-name.mdx
index d18994f7c7..d6db40adeb 100644
--- a/docs/api-reference/endpoints/app-connections/aws/get-by-name.mdx
+++ b/docs/api-reference/endpoints/app-connections/aws/get-by-name.mdx
@@ -1,4 +1,4 @@
 ---
 title: "Get by Name"
-openapi: "GET /api/v1/app-connections/aws/name/{connectionName}"
+openapi: "GET /api/v1/app-connections/aws/connection-name/{connectionName}"
 ---
diff --git a/docs/api-reference/endpoints/app-connections/github/available.mdx b/docs/api-reference/endpoints/app-connections/github/available.mdx
new file mode 100644
index 0000000000..6d5596629f
--- /dev/null
+++ b/docs/api-reference/endpoints/app-connections/github/available.mdx
@@ -0,0 +1,4 @@
+---
+title: "Available"
+openapi: "GET /api/v1/app-connections/github/available"
+---
diff --git a/docs/api-reference/endpoints/app-connections/github/get-by-name.mdx b/docs/api-reference/endpoints/app-connections/github/get-by-name.mdx
index 95ddbd6e95..cf959827bc 100644
--- a/docs/api-reference/endpoints/app-connections/github/get-by-name.mdx
+++ b/docs/api-reference/endpoints/app-connections/github/get-by-name.mdx
@@ -1,4 +1,4 @@
 ---
 title: "Get by Name"
-openapi: "GET /api/v1/app-connections/github/name/{connectionName}"
+openapi: "GET /api/v1/app-connections/github/connection-name/{connectionName}"
 ---
diff --git a/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/create.mdx b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/create.mdx
new file mode 100644
index 0000000000..2e29b8a5a3
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/create.mdx
@@ -0,0 +1,4 @@
+---
+title: "Create"
+openapi: "POST /api/v1/secret-syncs/aws-parameter-store"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/delete.mdx b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/delete.mdx
new file mode 100644
index 0000000000..2c801aba3c
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/delete.mdx
@@ -0,0 +1,4 @@
+---
+title: "Delete"
+openapi: "DELETE /api/v1/secret-syncs/aws-parameter-store/{syncId}"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/get-by-id.mdx b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/get-by-id.mdx
new file mode 100644
index 0000000000..aeecf16e17
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/get-by-id.mdx
@@ -0,0 +1,4 @@
+---
+title: "Get by ID"
+openapi: "GET /api/v1/secret-syncs/aws-parameter-store/{syncId}"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/get-by-name.mdx b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/get-by-name.mdx
new file mode 100644
index 0000000000..67930be3cd
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/get-by-name.mdx
@@ -0,0 +1,4 @@
+---
+title: "Get by Name"
+openapi: "GET /api/v1/secret-syncs/aws-parameter-store/sync-name/{syncName}"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/import-secrets.mdx b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/import-secrets.mdx
new file mode 100644
index 0000000000..217fd849c3
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/import-secrets.mdx
@@ -0,0 +1,4 @@
+---
+title: "Import Secrets"
+openapi: "POST /api/v1/secret-syncs/aws-parameter-store/{syncId}/import-secrets"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/list.mdx b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/list.mdx
new file mode 100644
index 0000000000..8a0c2281da
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/list.mdx
@@ -0,0 +1,4 @@
+---
+title: "List"
+openapi: "GET /api/v1/secret-syncs/aws-parameter-store"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/remove-secrets.mdx b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/remove-secrets.mdx
new file mode 100644
index 0000000000..bc617b40d5
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/remove-secrets.mdx
@@ -0,0 +1,4 @@
+---
+title: "Remove Secrets"
+openapi: "POST /api/v1/secret-syncs/aws-parameter-store/{syncId}/remove-secrets"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/sync-secrets.mdx b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/sync-secrets.mdx
new file mode 100644
index 0000000000..12b7230542
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/sync-secrets.mdx
@@ -0,0 +1,4 @@
+---
+title: "Sync Secrets"
+openapi: "POST /api/v1/secret-syncs/aws-parameter-store/{syncId}/sync-secrets"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/update.mdx b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/update.mdx
new file mode 100644
index 0000000000..b290ddfa4f
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/aws-parameter-store/update.mdx
@@ -0,0 +1,4 @@
+---
+title: "Update"
+openapi: "PATCH /api/v1/secret-syncs/aws-parameter-store/{syncId}"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/github/create.mdx b/docs/api-reference/endpoints/secret-syncs/github/create.mdx
new file mode 100644
index 0000000000..d0260b8eaf
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/github/create.mdx
@@ -0,0 +1,4 @@
+---
+title: "Create"
+openapi: "POST /api/v1/secret-syncs/github"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/github/delete.mdx b/docs/api-reference/endpoints/secret-syncs/github/delete.mdx
new file mode 100644
index 0000000000..409a65cdab
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/github/delete.mdx
@@ -0,0 +1,4 @@
+---
+title: "Delete"
+openapi: "DELETE /api/v1/secret-syncs/github/{syncId}"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/github/get-by-id.mdx b/docs/api-reference/endpoints/secret-syncs/github/get-by-id.mdx
new file mode 100644
index 0000000000..d3c6da8481
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/github/get-by-id.mdx
@@ -0,0 +1,4 @@
+---
+title: "Get by ID"
+openapi: "GET /api/v1/secret-syncs/github/{syncId}"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/github/get-by-name.mdx b/docs/api-reference/endpoints/secret-syncs/github/get-by-name.mdx
new file mode 100644
index 0000000000..b4c17b4d81
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/github/get-by-name.mdx
@@ -0,0 +1,4 @@
+---
+title: "Get by Name"
+openapi: "GET /api/v1/secret-syncs/github/sync-name/{syncName}"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/github/list.mdx b/docs/api-reference/endpoints/secret-syncs/github/list.mdx
new file mode 100644
index 0000000000..c3c0e10ab1
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/github/list.mdx
@@ -0,0 +1,4 @@
+---
+title: "List"
+openapi: "GET /api/v1/secret-syncs/github"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/github/remove-secrets.mdx b/docs/api-reference/endpoints/secret-syncs/github/remove-secrets.mdx
new file mode 100644
index 0000000000..1c133da8ce
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/github/remove-secrets.mdx
@@ -0,0 +1,4 @@
+---
+title: "Remove Secrets"
+openapi: "POST /api/v1/secret-syncs/github/{syncId}/remove-secrets"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/github/sync-secrets.mdx b/docs/api-reference/endpoints/secret-syncs/github/sync-secrets.mdx
new file mode 100644
index 0000000000..e1bcf1045e
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/github/sync-secrets.mdx
@@ -0,0 +1,4 @@
+---
+title: "Sync Secrets"
+openapi: "POST /api/v1/secret-syncs/github/{syncId}/sync-secrets"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/github/update.mdx b/docs/api-reference/endpoints/secret-syncs/github/update.mdx
new file mode 100644
index 0000000000..62d30327e2
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/github/update.mdx
@@ -0,0 +1,4 @@
+---
+title: "Update"
+openapi: "PATCH /api/v1/secret-syncs/github/{syncId}"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/list.mdx b/docs/api-reference/endpoints/secret-syncs/list.mdx
new file mode 100644
index 0000000000..d18b47f9a3
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/list.mdx
@@ -0,0 +1,4 @@
+---
+title: "List"
+openapi: "GET /api/v1/secret-syncs"
+---
diff --git a/docs/api-reference/endpoints/secret-syncs/options.mdx b/docs/api-reference/endpoints/secret-syncs/options.mdx
new file mode 100644
index 0000000000..cc485111bd
--- /dev/null
+++ b/docs/api-reference/endpoints/secret-syncs/options.mdx
@@ -0,0 +1,4 @@
+---
+title: "Options"
+openapi: "GET /api/v1/secret-syncs/options"
+---
diff --git a/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-created.png b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-created.png
new file mode 100644
index 0000000000..009331fe6f
Binary files /dev/null and b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-created.png differ
diff --git a/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-destination.png b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-destination.png
new file mode 100644
index 0000000000..d7136cd9af
Binary files /dev/null and b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-destination.png differ
diff --git a/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-details.png b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-details.png
new file mode 100644
index 0000000000..2d4b59a3f4
Binary files /dev/null and b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-details.png differ
diff --git a/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-options.png b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-options.png
new file mode 100644
index 0000000000..11923e5a29
Binary files /dev/null and b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-options.png differ
diff --git a/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-review.png b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-review.png
new file mode 100644
index 0000000000..0db843edef
Binary files /dev/null and b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-review.png differ
diff --git a/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-source.png b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-source.png
new file mode 100644
index 0000000000..4a5ec9904f
Binary files /dev/null and b/docs/images/secret-syncs/aws-parameter-store/aws-parameter-store-source.png differ
diff --git a/docs/images/secret-syncs/aws-parameter-store/select-aws-parameter-store-option.png b/docs/images/secret-syncs/aws-parameter-store/select-aws-parameter-store-option.png
new file mode 100644
index 0000000000..d43a797153
Binary files /dev/null and b/docs/images/secret-syncs/aws-parameter-store/select-aws-parameter-store-option.png differ
diff --git a/docs/images/secret-syncs/general/secret-sync-tab.png b/docs/images/secret-syncs/general/secret-sync-tab.png
new file mode 100644
index 0000000000..dad8c2426f
Binary files /dev/null and b/docs/images/secret-syncs/general/secret-sync-tab.png differ
diff --git a/docs/images/secret-syncs/github/github-created.png b/docs/images/secret-syncs/github/github-created.png
new file mode 100644
index 0000000000..f3ab7241bd
Binary files /dev/null and b/docs/images/secret-syncs/github/github-created.png differ
diff --git a/docs/images/secret-syncs/github/github-destination.png b/docs/images/secret-syncs/github/github-destination.png
new file mode 100644
index 0000000000..3713932bb0
Binary files /dev/null and b/docs/images/secret-syncs/github/github-destination.png differ
diff --git a/docs/images/secret-syncs/github/github-details.png b/docs/images/secret-syncs/github/github-details.png
new file mode 100644
index 0000000000..a8cbbbb948
Binary files /dev/null and b/docs/images/secret-syncs/github/github-details.png differ
diff --git a/docs/images/secret-syncs/github/github-options.png b/docs/images/secret-syncs/github/github-options.png
new file mode 100644
index 0000000000..8f2e3a4baa
Binary files /dev/null and b/docs/images/secret-syncs/github/github-options.png differ
diff --git a/docs/images/secret-syncs/github/github-review.png b/docs/images/secret-syncs/github/github-review.png
new file mode 100644
index 0000000000..4cbed76b65
Binary files /dev/null and b/docs/images/secret-syncs/github/github-review.png differ
diff --git a/docs/images/secret-syncs/github/github-source.png b/docs/images/secret-syncs/github/github-source.png
new file mode 100644
index 0000000000..dd4bc3ec8b
Binary files /dev/null and b/docs/images/secret-syncs/github/github-source.png differ
diff --git a/docs/images/secret-syncs/github/select-github-option.png b/docs/images/secret-syncs/github/select-github-option.png
new file mode 100644
index 0000000000..ebee947b4f
Binary files /dev/null and b/docs/images/secret-syncs/github/select-github-option.png differ
diff --git a/docs/integrations/app-connections/aws.mdx b/docs/integrations/app-connections/aws.mdx
index 65af1bcdc2..1768477645 100644
--- a/docs/integrations/app-connections/aws.mdx
+++ b/docs/integrations/app-connections/aws.mdx
@@ -67,7 +67,7 @@ Infisical supports two methods for connecting to AWS.
                 Depending on your use case, add one or more of the following policies to your IAM Role:
 
                 <Tabs>
-                    <Tab title="Secrets Sync">
+                    <Tab title="Secret Sync">
                         <AccordionGroup>
                             <Accordion title="AWS Secrets Manager">
                                 Use the following custom policy to grant the minimum permissions required by Infisical to sync secrets to AWS Secrets Manager:
@@ -217,7 +217,7 @@ Infisical supports two methods for connecting to AWS.
                 Depending on your use case, add one or more of the following policies to your IAM Role:
 
                 <Tabs>
-                    <Tab title="Secrets Sync">
+                    <Tab title="Secret Sync">
                         <AccordionGroup>
                             <Accordion title="AWS Secrets Manager">
                                 Use the following custom policy to grant the minimum permissions required by Infisical to sync secrets to AWS Secrets Manager:
diff --git a/docs/integrations/app-connections/github.mdx b/docs/integrations/app-connections/github.mdx
index 18f702bb61..5d33bad582 100644
--- a/docs/integrations/app-connections/github.mdx
+++ b/docs/integrations/app-connections/github.mdx
@@ -23,7 +23,7 @@ Infisical supports two methods for connecting to GitHub.
 
                     ![integrations github app create](/images/integrations/github/app/self-hosted-github-app-create.png)
 
-                    Give the application a name, a homepage URL (your self-hosted domain i.e. `https://your-domain.com`), and a callback URL (i.e. `https://your-domain.com/app-connections/github/oauth/callback`).
+                    Give the application a name, a homepage URL (your self-hosted domain i.e. `https://your-domain.com`), and a callback URL (i.e. `https://your-domain.com/organization/app-connections/github/oauth/callback`).
 
                     ![integrations github app basic details](/images/integrations/github/app/self-hosted-github-app-basic-details.png)
 
@@ -116,7 +116,7 @@ Infisical supports two methods for connecting to GitHub.
                     ![integrations github config](../../images/integrations/github/integrations-github-config-new-app.png)
 
                     Create the OAuth application. As part of the form, set the **Homepage URL** to your self-hosted domain `https://your-domain.com`
-                    and the **Authorization callback URL** to `https://your-domain.com/app-connections/github/oauth/callback`.
+                    and the **Authorization callback URL** to `https://your-domain.com/organization/app-connections/github/oauth/callback`.
 
                     ![integrations github config](../../images/integrations/github/integrations-github-config-new-app-form.png)
 
diff --git a/docs/integrations/secret-syncs/aws-parameter-store.mdx b/docs/integrations/secret-syncs/aws-parameter-store.mdx
new file mode 100644
index 0000000000..a9055ff1ef
--- /dev/null
+++ b/docs/integrations/secret-syncs/aws-parameter-store.mdx
@@ -0,0 +1,139 @@
+---
+title: "AWS Parameter Store Sync"
+description: "Learn how to configure an AWS Parameter Store Sync for Infisical."
+---
+
+**Prerequisites:**
+
+        - Set up and add secrets to [Infisical Cloud](https://app.infisical.com)
+        - Create an [AWS Connection](/integrations/app-connections/aws) with the required **Secret Sync** permissions
+
+<Tabs>
+    <Tab title="Infisical UI">
+        1. Navigate to **Project** > **Integrations** and select the **Secret Syncs** tab. Click on the **Add Sync** button.
+        ![Secret Syncs Tab](/images/secret-syncs/general/secret-sync-tab.png)
+
+        2. Select the **AWS Parameter Store** option.
+        ![Select AWS Parameter Store](/images/secret-syncs/aws-parameter-store/select-aws-parameter-store-option.png)
+
+        3. Configure the **Source** from where secrets should be retrieved, then click **Next**.
+        ![Configure Source](/images/secret-syncs/aws-parameter-store/aws-parameter-store-source.png)
+
+            - **Environment**: The project environment to retrieve secrets from.
+            - **Secret Path**: The folder path to retrieve secrets from.
+
+        <Tip>
+            If you need to sync secrets from multiple folder locations, check out [secret imports](/documentation/platform/secret-reference#secret-imports).
+        </Tip>
+
+        4. Configure the **Destination** to where secrets should be deployed, then click **Next**.
+        ![Configure Destination](/images/secret-syncs/aws-parameter-store/aws-parameter-store-destination.png)
+
+            - **AWS Connection**: The AWS Connection to authenticate with.
+            - **Region**: The AWS region to deploy secrets to.
+            - **Path**: The AWS Parameter Store path to deploy secrets to.
+
+        5. Configure the **Sync Options** to specify how secrets should be synced, then click **Next**.
+        ![Configure Options](/images/secret-syncs/aws-parameter-store/aws-parameter-store-options.png)
+
+            - **Initial Sync Behavior**: Determines how Infisical should resolve the initial sync.
+                - **Overwrite Destination Secrets**: Removes any secrets at the destination endpoint not present in Infisical.
+                - **Import Secrets (Prioritize Infisical)**: Imports secrets from the destination endpoint prior to syncing, prioritizing values present in Infisical if secrets conflict.
+                - **Import Secrets (Prioritize Parameter Store)**: Imports secrets from the destination endpoint prior to syncing, prioritizing values present in Parameter Store if secrets conflict.
+            - **Auto-Sync Enabled**: If enabled, secrets will automatically be synced from the source location when changes occur. Disable to enforce manual syncing only.
+
+        6. Configure the **Details** of your Parameter Store Sync, then click **Next**.
+        ![Configure Details](/images/secret-syncs/aws-parameter-store/aws-parameter-store-details.png)
+
+            - **Name**: The name of your sync. Must be slug-friendly.
+            - **Description**: An optional description for your sync.
+
+        7. Review your Parameter Store Sync configuration, then click **Create Sync**.
+        ![Confirm Configuration](/images/secret-syncs/aws-parameter-store/aws-parameter-store-review.png)
+
+        8. If enabled, your Parameter Store Sync will begin syncing your secrets to the destination endpoint.
+        ![Sync Secrets](/images/secret-syncs/aws-parameter-store/aws-parameter-store-created.png)
+
+    </Tab>
+    <Tab title="API">
+        To create an **AWS Parameter Store Sync**, make an API request to the [Create AWS
+        Parameter Store Sync](/api-reference/endpoints/secret-syncs/aws-parameter-store/create) API endpoint.
+
+        ### Sample request
+
+        ```bash Request
+        curl    --request POST \
+        --url https://app.infisical.com/api/v1/secret-syncs/aws-parameter-store \
+        --header 'Content-Type: application/json' \
+        --data '{
+            "name": "my-parameter-store-sync",
+            "projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+            "description": "an example sync",
+            "connectionId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+            "environment": "dev",
+            "secretPath": "/my-secrets",
+            "isEnabled": true,
+            "syncOptions": {
+                "initialSyncBehavior": "overwrite-destination"
+            },
+            "destinationConfig": {
+                "region": "us-east-1",
+                "path": "/my-aws/path/"
+            }
+        }'
+        ```
+
+        ### Sample response
+
+        ```bash Response
+        {
+            "secretSync": {
+                "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+                "name": "my-parameter-store-sync",
+                "description": "an example sync",
+                "isEnabled": true,
+                "version": 1,
+                "folderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+                "connectionId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+                "createdAt": "2023-11-07T05:31:56Z",
+                "updatedAt": "2023-11-07T05:31:56Z",
+                "syncStatus": "succeeded",
+                "lastSyncJobId": "123",
+                "lastSyncMessage": null,
+                "lastSyncedAt": "2023-11-07T05:31:56Z",
+                "importStatus": null,
+                "lastImportJobId": null,
+                "lastImportMessage": null,
+                "lastImportedAt": null,
+                "removeStatus": null,
+                "lastRemoveJobId": null,
+                "lastRemoveMessage": null,
+                "lastRemovedAt": null,
+                "syncOptions": {
+                    "initialSyncBehavior": "overwrite-destination"
+                },
+                "projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+                "connection": {
+                    "app": "aws",
+                    "name": "my-aws-connection",
+                    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
+                },
+                "environment": {
+                    "slug": "dev",
+                    "name": "Development",
+                    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
+                },
+                "folder": {
+                    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+                    "path": "/my-secrets"
+                },
+                "destination": "aws-parameter-store",
+                "destinationConfig": {
+                    "region": "us-east-1",
+                    "path": "/my-aws/path/"
+                }
+            }
+        }
+        ```
+    </Tab>
+</Tabs>
diff --git a/docs/integrations/secret-syncs/github.mdx b/docs/integrations/secret-syncs/github.mdx
new file mode 100644
index 0000000000..4c6d52efba
--- /dev/null
+++ b/docs/integrations/secret-syncs/github.mdx
@@ -0,0 +1,162 @@
+---
+title: "GitHub Sync"
+description: "Learn how to configure a GitHub Sync for Infisical."
+---
+
+**Prerequisites:**
+
+        - Set up and add secrets to [Infisical Cloud](https://app.infisical.com)
+        - Create a [GitHub Connection](/integrations/app-connections/github)
+
+<Tabs>
+    <Tab title="Infisical UI">
+        1. Navigate to **Project** > **Integrations** and select the **Secret Syncs** tab. Click on the **Add Sync** button.
+        ![Secret Syncs Tab](/images/secret-syncs/general/secret-sync-tab.png)
+
+        2. Select the **GitHub Store** option.
+        ![Select GitHub](/images/secret-syncs/github/select-github-option.png)
+
+        3. Configure the **Source** from where secrets should be retrieved, then click **Next**.
+        ![Configure Source](/images/secret-syncs/github/github-source.png)
+
+            - **Environment**: The project environment to retrieve secrets from.
+            - **Secret Path**: The folder path to retrieve secrets from.
+
+        <Tip>
+            If you need to sync secrets from multiple folder locations, check out [secret imports](/documentation/platform/secret-reference#secret-imports).
+        </Tip>
+
+        4. Configure the **Destination** to where secrets should be deployed, then click **Next**.
+        ![Configure Destination](/images/secret-syncs/github/github-destination.png)
+
+            - **GitHub Connection**: The GitHub Connection to authenticate with.
+            - **Scope**: The GitHub secret scope to sync secrets to.
+                - **Organization**: Sync secrets to a specific organization.
+                - **Repository**: Sync secrets to a specific repository.
+                - **Repository Environment**: Sync secrets to a specific repository's environment.
+            <p class="height:1px"  />
+            The remaining fields are determined by the selected **Scope**:
+            <AccordionGroup>
+                <Accordion title="Organization">
+                    - **Organization**: The organization to deploy secrets to.
+                    - **Visibility**: Determines which organization repositories can access deployed secrets.
+                        - **All Repositories**: All repositories of the organization. (Public repositories if not a Pro/Team account)
+                        - **Private Repositories**: All private repositories of the organization. (Requires Pro/Team account)
+                        - **Selected Repositories**: Only the selected Repositories.
+                    - **Selected Repositories**: The selected repositories if **Visibility** is set to **Selected Repositories**.
+                </Accordion>
+                <Accordion title="Repository">
+                    - **Repository**: The repository to deploy secrets to.
+                </Accordion>
+                <Accordion title="Repository Environment">
+                    - **Repository**: The repository to deploy secrets to.
+                    - **Environment**: The repository's environment to deploy secrets to.
+                </Accordion>
+            </AccordionGroup>
+
+        5. Configure the **Sync Options** to specify how secrets should be synced, then click **Next**.
+        ![Configure Options](/images/secret-syncs/github/github-options.png)
+
+            - **Initial Sync Behavior**: Determines how Infisical should resolve the initial sync.
+                - **Overwrite Destination Secrets**: Removes any secrets at the destination endpoint not present in Infisical.
+                <Note>
+                    GitHub does not support importing secrets.
+                </Note>
+            - **Auto-Sync Enabled**: If enabled, secrets will automatically be synced from the source location when changes occur. Disable to enforce manual syncing only.
+
+        6. Configure the **Details** of your GitHub Sync, then click **Next**.
+        ![Configure Details](/images/secret-syncs/github/github-details.png)
+
+            - **Name**: The name of your sync. Must be slug-friendly.
+            - **Description**: An optional description for your sync.
+
+        7. Review your GitHub Sync configuration, then click **Create Sync**.
+        ![Confirm Configuration](/images/secret-syncs/github/github-review.png)
+
+        8. If enabled, your GitHub Sync will begin syncing your secrets to the destination endpoint.
+        ![Sync Secrets](/images/secret-syncs/github/github-created.png)
+
+    </Tab>
+    <Tab title="API">
+        To create an **GitHub Sync**, make an API request to the [Create GitHub Sync](/api-reference/endpoints/secret-syncs/github/create) API endpoint.
+
+        ### Sample request
+
+        ```bash Request
+        curl    --request POST \
+        --url https://app.infisical.com/api/v1/secret-syncs/github \
+        --header 'Content-Type: application/json' \
+        --data '{
+            "name": "my-github-sync",
+            "projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+            "description": "an example sync",
+            "connectionId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+            "environment": "dev",
+            "secretPath": "/my-secrets",
+            "isEnabled": true,
+            "syncOptions": {
+                "initialSyncBehavior": "overwrite-destination"
+            },
+            "destinationConfig": {
+                "scope": "repository",
+                "owner": "my-github",
+                "repo": "my-repository"
+            }
+        }'
+        ```
+
+        ### Sample response
+
+        ```bash Response
+        {
+            "secretSync": {
+                "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+                "name": "my-github-sync",
+                "description": "an example sync",
+                "isEnabled": true,
+                "version": 1,
+                "folderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+                "connectionId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+                "createdAt": "2023-11-07T05:31:56Z",
+                "updatedAt": "2023-11-07T05:31:56Z",
+                "syncStatus": "succeeded",
+                "lastSyncJobId": "123",
+                "lastSyncMessage": null,
+                "lastSyncedAt": "2023-11-07T05:31:56Z",
+                "importStatus": null,
+                "lastImportJobId": null,
+                "lastImportMessage": null,
+                "lastImportedAt": null,
+                "removeStatus": null,
+                "lastRemoveJobId": null,
+                "lastRemoveMessage": null,
+                "lastRemovedAt": null,
+                "syncOptions": {
+                    "initialSyncBehavior": "overwrite-destination"
+                },
+                "projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+                "connection": {
+                    "app": "github",
+                    "name": "my-github-connection",
+                    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
+                },
+                "environment": {
+                    "slug": "dev",
+                    "name": "Development",
+                    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
+                },
+                "folder": {
+                    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
+                    "path": "/my-secrets"
+                },
+                "destination": "github",
+                "destinationConfig": {
+                    "scope": "repository",
+                    "owner": "my-github",
+                    "repo": "my-repository"
+                }
+            }
+        }
+        ```
+    </Tab>
+</Tabs>
diff --git a/docs/integrations/secret-syncs/overview.mdx b/docs/integrations/secret-syncs/overview.mdx
new file mode 100644
index 0000000000..cc93d80362
--- /dev/null
+++ b/docs/integrations/secret-syncs/overview.mdx
@@ -0,0 +1,89 @@
+---
+sidebarTitle: "Overview"
+description: "Learn how to sync secrets to third-party services with Infisical."
+---
+
+Secret Syncs enable you to sync secrets from Infisical to third-party services using [App Connections](/integrations/app-connections/overview).
+
+<Note>
+    Secret Syncs will gradually replace Native Integrations as they become available. Native Integrations will be deprecated in the future, so opt for configuring a Secret Sync when available.
+</Note>
+
+## Concept
+
+Secret Syncs are a project-level resource used to sync secrets, via an [App Connection](/integrations/app-connections/overview), from a particular project environment and folder path (source)
+to a third-party service (destination). Changes to the source will automatically be propagated to the destination, ensuring
+your secrets are always up-to-date.
+
+<br />
+
+<div align="center">
+
+    ```mermaid
+    %%{init: {'flowchart': {'curve': 'linear'} } }%%
+    graph LR
+    A[App Connection]
+    B[Secret Sync]
+    C[Secret 1]
+    D[Secret 2]
+    E[Secret 3]
+    F[Third-Party Service]
+    G[Secret 1]
+    H[Secret 2]
+    I[Secret 3]
+    J[Project Source]
+
+    B --> A
+    C --> J
+    D --> J
+    E --> J
+    A --> F
+    F --> G
+    F --> H
+    F --> I
+    J --> B
+
+    classDef default fill:#ffffff,stroke:#666,stroke-width:2px,rx:10px,color:black
+    classDef connection fill:#FFF2B2,stroke:#E6C34A,stroke-width:2px,color:black,rx:15px
+    classDef secret fill:#E6F4FF,stroke:#0096D6,stroke-width:2px,color:black,rx:15px
+    classDef sync fill:#F4FFE6,stroke:#96D600,stroke-width:2px,color:black,rx:15px
+    classDef service fill:#E6E6FF,stroke:#6B4E96,stroke-width:2px,color:black,rx:15px
+    classDef project fill:#FFE6E6,stroke:#D63F3F,stroke-width:2px,color:black,rx:15px
+
+    class A connection
+    class B sync
+    class C,D,E,G,H,I secret
+    class F project
+    class J service
+    ```
+
+</div>
+
+## Workflow
+
+Configuring a Secret Sync requires three components: a <strong>source</strong> location to retrieve secrets from,
+a <strong>destination</strong> endpoint to deploy secrets to, and <strong>configuration options</strong> to determine how your secrets
+should be synced. Follow these steps to start syncing:
+
+<Note>
+    For step-by-step guides on syncing to a particular third-party service, refer to the Secret Syncs section in the Navigation Bar.
+</Note>
+
+1. <strong>Create App Connection:</strong> If you have not already done so, create an [App Connection](/integrations/app-connections/overview)
+via the UI or API for the third-party service you intend to sync secrets to.
+
+2. <strong>Create Secret Sync:</strong> Configure a Secret Sync in the desired project by specifying the following parameters via the UI or API:
+    - <strong>Source:</strong> The project environment and folder path you wish to retrieve secrets from.
+    - <strong>Destination:</strong> The App Connection to utilize and the destination endpoint to deploy secrets to. These can vary between services.
+    - <strong>Options:</strong> Customize how secrets should be synced. Examples include adding a suffix or prefix to your secrets, or importing secrets from the destination on the initial sync.
+
+<Info>
+    Some third-party services do not support importing secrets.
+</Info>
+
+3. <strong>Utilize Sync:</strong> Any changes to the source location will now automatically be propagated to the destination endpoint.
+
+<Note>
+    Infisical is continuously expanding it's Secret Sync third-party service support. If the service you need isn't available,
+    you can still use our Native Integrations in the interim, or contact us at team@infisical.com to make a request .
+</Note>
\ No newline at end of file
diff --git a/docs/mint.json b/docs/mint.json
index 26d199fcef..23b10f5795 100644
--- a/docs/mint.json
+++ b/docs/mint.json
@@ -343,6 +343,22 @@
         "cli/faq"
       ]
     },
+    {
+      "group": "App Connections",
+      "pages": [
+        "integrations/app-connections/overview",
+        "integrations/app-connections/aws",
+        "integrations/app-connections/github"
+      ]
+    },
+    {
+      "group": "Secret Syncs",
+      "pages": [
+        "integrations/secret-syncs/overview",
+        "integrations/secret-syncs/aws-parameter-store",
+        "integrations/secret-syncs/github"
+      ]
+    },
     {
       "group": "Infrastructure Integrations",
       "pages": [
@@ -767,6 +783,67 @@
             "api-reference/endpoints/identity-specific-privilege/list"
           ]
         },
+        {
+          "group": "App Connections",
+          "pages": [
+            "api-reference/endpoints/app-connections/list",
+            "api-reference/endpoints/app-connections/options",
+            { "group":  "AWS",
+              "pages": [
+                "api-reference/endpoints/app-connections/aws/list",
+                "api-reference/endpoints/app-connections/aws/available",
+                "api-reference/endpoints/app-connections/aws/get-by-id",
+                "api-reference/endpoints/app-connections/aws/get-by-name",
+                "api-reference/endpoints/app-connections/aws/create",
+                "api-reference/endpoints/app-connections/aws/update",
+                "api-reference/endpoints/app-connections/aws/delete"
+              ]
+            },
+            { "group":  "GitHub",
+              "pages": [
+                "api-reference/endpoints/app-connections/github/list",
+                "api-reference/endpoints/app-connections/github/available",
+                "api-reference/endpoints/app-connections/github/get-by-id",
+                "api-reference/endpoints/app-connections/github/get-by-name",
+                "api-reference/endpoints/app-connections/github/create",
+                "api-reference/endpoints/app-connections/github/update",
+                "api-reference/endpoints/app-connections/github/delete"
+              ]
+            }
+          ]
+        },
+        {
+          "group": "Secret Syncs",
+          "pages": [
+            "api-reference/endpoints/secret-syncs/list",
+            "api-reference/endpoints/secret-syncs/options",
+            { "group":  "AWS Parameter Store",
+              "pages": [
+                "api-reference/endpoints/secret-syncs/aws-parameter-store/list",
+                "api-reference/endpoints/secret-syncs/aws-parameter-store/get-by-id",
+                "api-reference/endpoints/secret-syncs/aws-parameter-store/get-by-name",
+                "api-reference/endpoints/secret-syncs/aws-parameter-store/create",
+                "api-reference/endpoints/secret-syncs/aws-parameter-store/update",
+                "api-reference/endpoints/secret-syncs/aws-parameter-store/delete",
+                "api-reference/endpoints/secret-syncs/aws-parameter-store/sync-secrets",
+                "api-reference/endpoints/secret-syncs/aws-parameter-store/import-secrets",
+                "api-reference/endpoints/secret-syncs/aws-parameter-store/remove-secrets"
+              ]
+            },
+            { "group":  "GitHub",
+              "pages": [
+                "api-reference/endpoints/secret-syncs/github/list",
+                "api-reference/endpoints/secret-syncs/github/get-by-id",
+                "api-reference/endpoints/secret-syncs/github/get-by-name",
+                "api-reference/endpoints/secret-syncs/github/create",
+                "api-reference/endpoints/secret-syncs/github/update",
+                "api-reference/endpoints/secret-syncs/github/delete",
+                "api-reference/endpoints/secret-syncs/github/sync-secrets",
+                "api-reference/endpoints/secret-syncs/github/remove-secrets"
+              ]
+            }
+          ]
+        },
         {
           "group": "Integrations",
           "pages": [
diff --git a/frontend/src/components/secret-syncs/CreateSecretSyncModal.tsx b/frontend/src/components/secret-syncs/CreateSecretSyncModal.tsx
new file mode 100644
index 0000000000..3e232765cf
--- /dev/null
+++ b/frontend/src/components/secret-syncs/CreateSecretSyncModal.tsx
@@ -0,0 +1,70 @@
+import { useState } from "react";
+
+import { Modal, ModalContent } from "@app/components/v2";
+import { SecretSync, TSecretSync } from "@app/hooks/api/secretSyncs";
+
+import { CreateSecretSyncForm } from "./forms";
+import { SecretSyncModalHeader } from "./SecretSyncModalHeader";
+import { SecretSyncSelect } from "./SecretSyncSelect";
+
+type Props = {
+  isOpen: boolean;
+  onOpenChange: (isOpen: boolean) => void;
+};
+
+type ContentProps = {
+  onComplete: (secretSync: TSecretSync) => void;
+  selectedSync: SecretSync | null;
+  setSelectedSync: (selectedSync: SecretSync | null) => void;
+};
+
+const Content = ({ onComplete, setSelectedSync, selectedSync }: ContentProps) => {
+  if (selectedSync) {
+    return (
+      <CreateSecretSyncForm
+        onComplete={onComplete}
+        onCancel={() => setSelectedSync(null)}
+        destination={selectedSync}
+      />
+    );
+  }
+
+  return <SecretSyncSelect onSelect={setSelectedSync} />;
+};
+
+export const CreateSecretSyncModal = ({ onOpenChange, ...props }: Props) => {
+  const [selectedSync, setSelectedSync] = useState<SecretSync | null>(null);
+
+  return (
+    <Modal
+      {...props}
+      onOpenChange={(isOpen) => {
+        if (!isOpen) setSelectedSync(null);
+        onOpenChange(isOpen);
+      }}
+    >
+      <ModalContent
+        title={
+          selectedSync ? (
+            <SecretSyncModalHeader isConfigured={false} destination={selectedSync} />
+          ) : (
+            "Add Sync"
+          )
+        }
+        onPointerDownOutside={(e) => e.preventDefault()}
+        className="max-w-2xl"
+        subTitle={selectedSync ? undefined : "Select a third-party service to sync secrets to."}
+        bodyClassName="overflow-visible"
+      >
+        <Content
+          onComplete={() => {
+            setSelectedSync(null);
+            onOpenChange(false);
+          }}
+          selectedSync={selectedSync}
+          setSelectedSync={setSelectedSync}
+        />
+      </ModalContent>
+    </Modal>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/DeleteSecretSyncModal.tsx b/frontend/src/components/secret-syncs/DeleteSecretSyncModal.tsx
new file mode 100644
index 0000000000..1daed67a38
--- /dev/null
+++ b/frontend/src/components/secret-syncs/DeleteSecretSyncModal.tsx
@@ -0,0 +1,70 @@
+import { useState } from "react";
+
+import { createNotification } from "@app/components/notifications";
+import { DeleteActionModal, Switch } from "@app/components/v2";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { TSecretSync, useDeleteSecretSync } from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  secretSync?: TSecretSync;
+  isOpen: boolean;
+  onOpenChange: (isOpen: boolean) => void;
+  onComplete?: () => void;
+};
+
+export const DeleteSecretSyncModal = ({ isOpen, onOpenChange, secretSync, onComplete }: Props) => {
+  const deleteSync = useDeleteSecretSync();
+  const [removeSecrets, setRemoveSecrets] = useState(false);
+
+  if (!secretSync) return null;
+
+  const { id: syncId, name, destination } = secretSync;
+
+  const handleDeleteSecretSync = async () => {
+    const destinationName = SECRET_SYNC_MAP[destination].name;
+
+    try {
+      await deleteSync.mutateAsync({
+        syncId,
+        destination,
+        removeSecrets
+      });
+
+      createNotification({
+        text: `Successfully removed ${destinationName} Sync`,
+        type: "success"
+      });
+
+      if (onComplete) onComplete();
+      onOpenChange(false);
+    } catch (err) {
+      console.error(err);
+
+      createNotification({
+        text: `Failed to remove ${destinationName} Sync`,
+        type: "error"
+      });
+    }
+  };
+
+  return (
+    <DeleteActionModal
+      isOpen={isOpen}
+      onChange={onOpenChange}
+      title={`Are you sure want to delete ${name}?`}
+      deleteKey={name}
+      onDeleteApproved={handleDeleteSecretSync}
+    >
+      <Switch
+        containerClassName="mt-4"
+        className="bg-mineshaft-400/50 shadow-inner data-[state=checked]:bg-red/50"
+        thumbClassName="bg-mineshaft-800"
+        isChecked={removeSecrets}
+        onCheckedChange={setRemoveSecrets}
+        id="remove-secrets"
+      >
+        Remove Synced Secrets
+      </Switch>
+    </DeleteActionModal>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/EditSecretSyncModal.tsx b/frontend/src/components/secret-syncs/EditSecretSyncModal.tsx
new file mode 100644
index 0000000000..c7d0661d31
--- /dev/null
+++ b/frontend/src/components/secret-syncs/EditSecretSyncModal.tsx
@@ -0,0 +1,33 @@
+import { SecretSyncEditFields } from "@app/components/secret-syncs/types";
+import { Modal, ModalContent } from "@app/components/v2";
+import { TSecretSync } from "@app/hooks/api/secretSyncs";
+
+import { EditSecretSyncForm } from "./forms";
+import { SecretSyncModalHeader } from "./SecretSyncModalHeader";
+
+type Props = {
+  isOpen: boolean;
+  onOpenChange: (isOpen: boolean) => void;
+  secretSync?: TSecretSync;
+  fields: SecretSyncEditFields;
+};
+
+export const EditSecretSyncModal = ({ secretSync, onOpenChange, fields, ...props }: Props) => {
+  if (!secretSync) return null;
+
+  return (
+    <Modal {...props} onOpenChange={onOpenChange}>
+      <ModalContent
+        title={<SecretSyncModalHeader isConfigured destination={secretSync.destination} />}
+        className="max-w-2xl"
+        bodyClassName="overflow-visible"
+      >
+        <EditSecretSyncForm
+          onComplete={() => onOpenChange(false)}
+          fields={fields}
+          secretSync={secretSync}
+        />
+      </ModalContent>
+    </Modal>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/SecretSyncImportSecretsModal.tsx b/frontend/src/components/secret-syncs/SecretSyncImportSecretsModal.tsx
new file mode 100644
index 0000000000..aab8a42436
--- /dev/null
+++ b/frontend/src/components/secret-syncs/SecretSyncImportSecretsModal.tsx
@@ -0,0 +1,167 @@
+import { Controller, useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { z } from "zod";
+
+import { createNotification } from "@app/components/notifications";
+import {
+  Button,
+  FormControl,
+  Modal,
+  ModalClose,
+  ModalContent,
+  Select,
+  SelectItem
+} from "@app/components/v2";
+import { SECRET_SYNC_IMPORT_BEHAVIOR_MAP, SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import {
+  SecretSyncImportBehavior,
+  TSecretSync,
+  useTriggerSecretSyncImportSecrets
+} from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  secretSync?: TSecretSync;
+  isOpen: boolean;
+  onOpenChange: (isOpen: boolean) => void;
+};
+
+type ContentProps = {
+  secretSync: TSecretSync;
+  onComplete: () => void;
+};
+
+const FormSchema = z.object({
+  importBehavior: z.nativeEnum(SecretSyncImportBehavior)
+});
+
+type TFormData = z.infer<typeof FormSchema>;
+
+const Content = ({ secretSync, onComplete }: ContentProps) => {
+  const { id: syncId, destination } = secretSync;
+  const destinationName = SECRET_SYNC_MAP[destination].name;
+
+  const {
+    handleSubmit,
+    control,
+    formState: { isSubmitting, isDirty }
+  } = useForm<TFormData>({ resolver: zodResolver(FormSchema) });
+
+  const triggerImportSecrets = useTriggerSecretSyncImportSecrets();
+
+  const handleTriggerImportSecrets = async ({ importBehavior }: TFormData) => {
+    try {
+      await triggerImportSecrets.mutateAsync({
+        syncId,
+        destination,
+        importBehavior
+      });
+
+      createNotification({
+        text: `Successfully triggered secret import for ${destinationName} Sync`,
+        type: "success"
+      });
+
+      onComplete();
+    } catch (err) {
+      console.error(err);
+
+      createNotification({
+        text: `Failed to trigger secret import for ${destinationName} Sync`,
+        type: "error"
+      });
+    }
+  };
+
+  return (
+    <form onSubmit={handleSubmit(handleTriggerImportSecrets)}>
+      <p className="mb-8 text-sm text-mineshaft-200">
+        Are you sure you want to import secrets from this {destinationName} destination into
+        Infiscal?
+      </p>
+      <Controller
+        name="importBehavior"
+        control={control}
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl
+            tooltipClassName="max-w-lg py-3"
+            tooltipText={
+              <div className="flex flex-col gap-3">
+                <p>
+                  Specify how Infisical should resolve the initial sync to {destinationName}. The
+                  following options are available:
+                </p>
+                <ul className="flex list-disc flex-col gap-3 pl-4">
+                  {Object.values(SECRET_SYNC_IMPORT_BEHAVIOR_MAP).map((details) => {
+                    const { name, description } = details(destinationName);
+
+                    return (
+                      <li key={name}>
+                        <p className="text-mineshaft-300">
+                          <span className="font-medium text-bunker-200">{name}</span>: {description}
+                        </p>
+                      </li>
+                    );
+                  })}
+                </ul>
+              </div>
+            }
+            errorText={error?.message}
+            isError={Boolean(error?.message)}
+            label="Import Behavior"
+          >
+            <Select
+              value={value}
+              onValueChange={(val) => onChange(val)}
+              className="w-full border border-mineshaft-500"
+              position="popper"
+              placeholder="Select an option..."
+              dropdownContainerClassName="max-w-none"
+            >
+              {Object.entries(SECRET_SYNC_IMPORT_BEHAVIOR_MAP).map(([key, details]) => {
+                const { name } = details(destinationName);
+
+                return (
+                  <SelectItem value={key} key={key}>
+                    {name}
+                  </SelectItem>
+                );
+              })}
+            </Select>
+          </FormControl>
+        )}
+      />
+      <div className="mt-8 flex w-full items-center justify-between gap-2">
+        <ModalClose asChild>
+          <Button colorSchema="secondary" variant="plain">
+            Cancel
+          </Button>
+        </ModalClose>
+        <Button
+          type="submit"
+          isDisabled={isSubmitting || !isDirty}
+          isLoading={isSubmitting}
+          colorSchema="secondary"
+        >
+          Import Secrets
+        </Button>
+      </div>
+    </form>
+  );
+};
+
+export const SecretSyncImportSecretsModal = ({ isOpen, onOpenChange, secretSync }: Props) => {
+  if (!secretSync) return null;
+
+  const destinationName = SECRET_SYNC_MAP[secretSync.destination].name;
+
+  return (
+    <Modal isOpen={isOpen} onOpenChange={onOpenChange}>
+      <ModalContent
+        title="Import Secrets"
+        subTitle={`Import secrets into Infisical from this ${destinationName} Sync destination.`}
+      >
+        <Content secretSync={secretSync} onComplete={() => onOpenChange(false)} />
+      </ModalContent>
+    </Modal>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/SecretSyncImportStatusBadge.tsx b/frontend/src/components/secret-syncs/SecretSyncImportStatusBadge.tsx
new file mode 100644
index 0000000000..5f54d5c617
--- /dev/null
+++ b/frontend/src/components/secret-syncs/SecretSyncImportStatusBadge.tsx
@@ -0,0 +1,112 @@
+import { ReactNode, useEffect, useMemo, useState } from "react";
+import {
+  faCheck,
+  faDownload,
+  faTriangleExclamation,
+  faXmark,
+  IconDefinition
+} from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { differenceInSeconds } from "date-fns";
+import { twMerge } from "tailwind-merge";
+
+import { Badge, Tooltip } from "@app/components/v2";
+import { BadgeProps } from "@app/components/v2/Badge/Badge";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { SecretSyncStatus, TSecretSync } from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  secretSync: TSecretSync;
+  className?: string;
+  mini?: boolean;
+};
+
+export const SecretSyncImportStatusBadge = ({ secretSync, className, mini }: Props) => {
+  const { importStatus, lastImportMessage, lastImportedAt, destination } = secretSync;
+  const [hide, setHide] = useState(importStatus === SecretSyncStatus.Succeeded);
+  const destinationName = SECRET_SYNC_MAP[destination].name;
+
+  useEffect(() => {
+    if (importStatus === SecretSyncStatus.Succeeded) {
+      setTimeout(() => setHide(true), 3000);
+    } else {
+      setHide(false);
+    }
+  }, [importStatus]);
+
+  const failureMessage = useMemo(() => {
+    if (importStatus === SecretSyncStatus.Failed) {
+      if (lastImportMessage)
+        try {
+          return JSON.stringify(JSON.parse(lastImportMessage), null, 2);
+        } catch {
+          return lastImportMessage;
+        }
+
+      return "An Unknown Error Occurred.";
+    }
+    return null;
+  }, [importStatus, lastImportMessage]);
+
+  if (!importStatus || hide) return null;
+
+  let variant: BadgeProps["variant"];
+  let label: string;
+  let icon: IconDefinition;
+  let tooltipContent: ReactNode;
+
+  switch (importStatus) {
+    case SecretSyncStatus.Pending:
+    case SecretSyncStatus.Running:
+      variant = "primary";
+      label = "Importing Secrets...";
+      tooltipContent = `Importing secrets from ${destinationName}. This may take a moment.`;
+      icon = faDownload;
+
+      break;
+    case SecretSyncStatus.Failed:
+      variant = "danger";
+      label = "Failed to Import Secrets";
+      icon = faTriangleExclamation;
+      tooltipContent = (
+        <div className="flex flex-col gap-2 whitespace-normal py-1">
+          {failureMessage && (
+            <div>
+              <div className="mb-2 flex self-start text-red">
+                <FontAwesomeIcon icon={faXmark} className="ml-1 pr-1.5 pt-0.5 text-sm" />
+                <div className="text-xs">
+                  {mini ? "Failed to Import Secrets" : "Failure Reason"}
+                </div>
+              </div>
+              <div className="rounded bg-mineshaft-600 p-2 text-xs">{failureMessage}</div>
+            </div>
+          )}
+        </div>
+      );
+
+      break;
+    case SecretSyncStatus.Succeeded:
+    default:
+      // only show success for a bit...
+      if (lastImportedAt && differenceInSeconds(new Date(), lastImportedAt) > 15) return null;
+
+      tooltipContent = "Successfully imported secrets.";
+      variant = "success";
+      label = "Secrets Imported";
+      icon = faCheck;
+  }
+
+  return (
+    <Tooltip position="bottom" className="max-w-sm" content={tooltipContent}>
+      <div>
+        <Badge
+          className={twMerge("flex h-5 w-min items-center gap-1.5 whitespace-nowrap", className)}
+          variant={variant}
+        >
+          <FontAwesomeIcon icon={icon} />
+          {!mini && <span>{label}</span>}
+        </Badge>
+      </div>
+    </Tooltip>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/SecretSyncLabel.tsx b/frontend/src/components/secret-syncs/SecretSyncLabel.tsx
new file mode 100644
index 0000000000..8528c9bc6b
--- /dev/null
+++ b/frontend/src/components/secret-syncs/SecretSyncLabel.tsx
@@ -0,0 +1,22 @@
+import { ReactNode } from "react";
+import { twMerge } from "tailwind-merge";
+
+type Props = {
+  label: string;
+  children?: ReactNode;
+  className?: string;
+  labelClassName?: string;
+};
+
+export const SecretSyncLabel = ({ label, children, className, labelClassName }: Props) => {
+  return (
+    <div className={className}>
+      <p className={twMerge("text-xs font-medium text-mineshaft-400", labelClassName)}>{label}</p>
+      {children ? (
+        <p className="text-sm text-mineshaft-100">{children}</p>
+      ) : (
+        <p className="text-sm italic text-mineshaft-400/50">None</p>
+      )}
+    </div>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/SecretSyncModalHeader.tsx b/frontend/src/components/secret-syncs/SecretSyncModalHeader.tsx
new file mode 100644
index 0000000000..d8d07d9c9b
--- /dev/null
+++ b/frontend/src/components/secret-syncs/SecretSyncModalHeader.tsx
@@ -0,0 +1,49 @@
+import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  destination: SecretSync;
+  isConfigured: boolean;
+};
+
+export const SecretSyncModalHeader = ({ destination, isConfigured }: Props) => {
+  const destinationDetails = SECRET_SYNC_MAP[destination];
+
+  return (
+    <div className="flex w-full items-start gap-2">
+      <img
+        alt={`${destinationDetails.name} logo`}
+        src={`/images/integrations/${destinationDetails.image}`}
+        className="h-12 w-12 rounded-md bg-bunker-500 p-2"
+      />
+      <div>
+        <div className="flex items-center text-mineshaft-300">
+          {destinationDetails.name} Sync
+          <a
+            target="_blank"
+            href={`https://infisical.com/docs/integrations/secret-syncs/${destination}`}
+            className="mb-1 ml-1"
+            rel="noopener noreferrer"
+          >
+            <div className="inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
+              <FontAwesomeIcon icon={faBookOpen} className="mb-[0.03rem] mr-1 text-[12px]" />
+              <span>Docs</span>
+              <FontAwesomeIcon
+                icon={faArrowUpRightFromSquare}
+                className="mb-[0.07rem] ml-1 text-[10px]"
+              />
+            </div>
+          </a>
+        </div>
+        <p className="text-sm leading-4 text-mineshaft-400">
+          {isConfigured
+            ? `Edit ${destinationDetails.name} Sync`
+            : `Sync secrets to ${destinationDetails.name}`}
+        </p>
+      </div>
+    </div>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/SecretSyncRemoveSecretsModal.tsx b/frontend/src/components/secret-syncs/SecretSyncRemoveSecretsModal.tsx
new file mode 100644
index 0000000000..c8bdeee6d4
--- /dev/null
+++ b/frontend/src/components/secret-syncs/SecretSyncRemoveSecretsModal.tsx
@@ -0,0 +1,85 @@
+import { createNotification } from "@app/components/notifications";
+import { Button, Modal, ModalClose, ModalContent } from "@app/components/v2";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { TSecretSync, useTriggerSecretSyncRemoveSecrets } from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  secretSync?: TSecretSync;
+  isOpen: boolean;
+  onOpenChange: (isOpen: boolean) => void;
+};
+
+type ContentProps = {
+  secretSync: TSecretSync;
+  onComplete: () => void;
+};
+
+const Content = ({ secretSync, onComplete }: ContentProps) => {
+  const { id: syncId, destination } = secretSync;
+  const destinationName = SECRET_SYNC_MAP[destination].name;
+
+  const triggerSyncImport = useTriggerSecretSyncRemoveSecrets();
+
+  const handleTriggerRemoveSecrets = async () => {
+    try {
+      await triggerSyncImport.mutateAsync({
+        syncId,
+        destination
+      });
+
+      createNotification({
+        text: `Successfully triggered secret removal for ${destinationName} Sync`,
+        type: "success"
+      });
+
+      onComplete();
+    } catch (err) {
+      console.error(err);
+
+      createNotification({
+        text: `Failed to trigger secret removal for ${destinationName} Sync`,
+        type: "error"
+      });
+    }
+  };
+
+  return (
+    <>
+      <p className="mb-8 text-sm text-mineshaft-200">
+        Are you sure you want to remove synced secrets from this {destinationName} destination?
+      </p>
+      <div className="mt-8 flex w-full items-center justify-between gap-2">
+        <ModalClose asChild>
+          <Button colorSchema="secondary" variant="plain">
+            Cancel
+          </Button>
+        </ModalClose>
+        <Button
+          isDisabled={triggerSyncImport.isPending}
+          isLoading={triggerSyncImport.isPending}
+          onClick={handleTriggerRemoveSecrets}
+          colorSchema="secondary"
+        >
+          Remove Secrets
+        </Button>
+      </div>
+    </>
+  );
+};
+
+export const SecretSyncRemoveSecretsModal = ({ isOpen, onOpenChange, secretSync }: Props) => {
+  if (!secretSync) return null;
+
+  const destinationName = SECRET_SYNC_MAP[secretSync.destination].name;
+
+  return (
+    <Modal isOpen={isOpen} onOpenChange={onOpenChange}>
+      <ModalContent
+        title="Remove Secrets"
+        subTitle={`Remove synced secrets from this ${destinationName} Sync destination.`}
+      >
+        <Content secretSync={secretSync} onComplete={() => onOpenChange(false)} />
+      </ModalContent>
+    </Modal>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/SecretSyncRemoveStatusBadge.tsx b/frontend/src/components/secret-syncs/SecretSyncRemoveStatusBadge.tsx
new file mode 100644
index 0000000000..81d6eab304
--- /dev/null
+++ b/frontend/src/components/secret-syncs/SecretSyncRemoveStatusBadge.tsx
@@ -0,0 +1,112 @@
+import { ReactNode, useEffect, useMemo, useState } from "react";
+import {
+  faCheck,
+  faEraser,
+  faTriangleExclamation,
+  faXmark,
+  IconDefinition
+} from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { differenceInSeconds } from "date-fns";
+import { twMerge } from "tailwind-merge";
+
+import { Badge, Tooltip } from "@app/components/v2";
+import { BadgeProps } from "@app/components/v2/Badge/Badge";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { SecretSyncStatus, TSecretSync } from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  secretSync: TSecretSync;
+  className?: string;
+  mini?: boolean;
+};
+
+export const SecretSyncRemoveStatusBadge = ({ secretSync, className, mini }: Props) => {
+  const { removeStatus, lastRemoveMessage, lastRemovedAt, destination } = secretSync;
+  const [hide, setHide] = useState(removeStatus === SecretSyncStatus.Succeeded);
+  const destinationName = SECRET_SYNC_MAP[destination].name;
+
+  useEffect(() => {
+    if (removeStatus === SecretSyncStatus.Succeeded) {
+      setTimeout(() => setHide(true), 3000);
+    } else {
+      setHide(false);
+    }
+  }, [removeStatus]);
+
+  const failureMessage = useMemo(() => {
+    if (removeStatus === SecretSyncStatus.Failed) {
+      if (lastRemoveMessage)
+        try {
+          return JSON.stringify(JSON.parse(lastRemoveMessage), null, 2);
+        } catch {
+          return lastRemoveMessage;
+        }
+
+      return "An Unknown Error Occurred.";
+    }
+    return null;
+  }, [removeStatus, lastRemoveMessage]);
+
+  if (!removeStatus || hide) return null;
+
+  let variant: BadgeProps["variant"];
+  let label: string;
+  let icon: IconDefinition;
+  let tooltipContent: ReactNode;
+
+  switch (removeStatus) {
+    case SecretSyncStatus.Pending:
+    case SecretSyncStatus.Running:
+      variant = "primary";
+      label = "Removing Secrets...";
+      tooltipContent = `Removing secrets from ${destinationName}. This may take a moment.`;
+      icon = faEraser;
+
+      break;
+    case SecretSyncStatus.Failed:
+      variant = "danger";
+      label = "Failed to Remove Secrets";
+      icon = faTriangleExclamation;
+      tooltipContent = (
+        <div className="flex flex-col gap-2 whitespace-normal py-1">
+          {failureMessage && (
+            <div>
+              <div className="mb-2 flex self-start text-red">
+                <FontAwesomeIcon icon={faXmark} className="ml-1 pr-1.5 pt-0.5 text-sm" />
+                <div className="text-xs">
+                  {mini ? "Failed to Remove Secrets" : "Failure Reason"}
+                </div>
+              </div>
+              <div className="rounded bg-mineshaft-600 p-2 text-xs">{failureMessage}</div>
+            </div>
+          )}
+        </div>
+      );
+
+      break;
+    case SecretSyncStatus.Succeeded:
+    default:
+      // only show success for a bit...
+      if (lastRemovedAt && differenceInSeconds(new Date(), lastRemovedAt) > 15) return null;
+
+      tooltipContent = "Successfully removed secrets.";
+      variant = "success";
+      label = "Secrets Removed";
+      icon = faCheck;
+  }
+
+  return (
+    <Tooltip position="bottom" className="max-w-sm" content={tooltipContent}>
+      <div>
+        <Badge
+          className={twMerge("flex h-5 w-min items-center gap-1.5 whitespace-nowrap", className)}
+          variant={variant}
+        >
+          <FontAwesomeIcon icon={icon} />
+          {!mini && <span>{label}</span>}
+        </Badge>
+      </div>
+    </Tooltip>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/SecretSyncSelect.tsx b/frontend/src/components/secret-syncs/SecretSyncSelect.tsx
new file mode 100644
index 0000000000..6e3030a01e
--- /dev/null
+++ b/frontend/src/components/secret-syncs/SecretSyncSelect.tsx
@@ -0,0 +1,88 @@
+import { faWrench } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { Spinner, Tooltip } from "@app/components/v2";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { SecretSync, useSecretSyncOptions } from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  onSelect: (destination: SecretSync) => void;
+};
+
+export const SecretSyncSelect = ({ onSelect }: Props) => {
+  const { isLoading, data: secretSyncOptions } = useSecretSyncOptions();
+
+  if (isLoading) {
+    return (
+      <div className="flex h-full flex-col items-center justify-center py-2.5">
+        <Spinner size="lg" className="text-mineshaft-500" />
+        <p className="mt-4 text-sm text-mineshaft-400">Loading options...</p>
+      </div>
+    );
+  }
+
+  return (
+    <div className="grid grid-cols-4 gap-2">
+      {secretSyncOptions?.map(({ destination }) => {
+        const { image, name } = SECRET_SYNC_MAP[destination];
+        return (
+          <button
+            type="button"
+            key={destination}
+            onClick={() => onSelect(destination)}
+            className="group relative flex h-28 cursor-pointer flex-col items-center justify-center rounded-md border border-mineshaft-600 bg-mineshaft-700 p-4 duration-200 hover:bg-mineshaft-600"
+          >
+            <img
+              src={`/images/integrations/${image}`}
+              height={40}
+              width={40}
+              className="mt-auto"
+              alt={`${name} logo`}
+            />
+            <div className="mt-auto max-w-xs text-center text-xs font-medium text-gray-300 duration-200 group-hover:text-gray-200">
+              {name}
+            </div>
+          </button>
+        );
+      })}
+      <Tooltip
+        side="bottom"
+        className="max-w-sm py-4"
+        content={
+          <>
+            <p className="mb-2">Infisical is constantly adding support for more services.</p>
+            <p>
+              {`If you don't see the third-party
+            service you're looking for,`}{" "}
+              <a
+                target="_blank"
+                className="underline hover:text-mineshaft-300"
+                href="https://infisical.com/slack"
+                rel="noopener noreferrer"
+              >
+                let us know on Slack
+              </a>{" "}
+              or{" "}
+              <a
+                target="_blank"
+                className="underline hover:text-mineshaft-300"
+                href="https://github.com/Infisical/infisical/discussions"
+                rel="noopener noreferrer"
+              >
+                make a request on GitHub
+              </a>
+              .
+            </p>
+          </>
+        }
+      >
+        <div className="group relative flex h-28 flex-col items-center justify-center rounded-md border border-dashed border-mineshaft-600 bg-mineshaft-800 p-4 hover:bg-mineshaft-900/50">
+          <FontAwesomeIcon className="mt-auto text-3xl" icon={faWrench} />
+          <div className="mt-auto max-w-xs text-center text-xs font-medium text-gray-300 duration-200 group-hover:text-gray-200">
+            Coming Soon
+          </div>
+        </div>
+      </Tooltip>
+    </div>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/SecretSyncStatusBadge.tsx b/frontend/src/components/secret-syncs/SecretSyncStatusBadge.tsx
new file mode 100644
index 0000000000..dbf543f616
--- /dev/null
+++ b/frontend/src/components/secret-syncs/SecretSyncStatusBadge.tsx
@@ -0,0 +1,47 @@
+import {
+  faCheck,
+  faExclamationTriangle,
+  faRotate,
+  IconDefinition
+} from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { Badge, BadgeProps } from "@app/components/v2/Badge/Badge";
+import { SecretSyncStatus } from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  status: SecretSyncStatus;
+} & Omit<BadgeProps, "children" | "variant">;
+
+export const SecretSyncStatusBadge = ({ status }: Props) => {
+  let variant: BadgeProps["variant"];
+  let text: string;
+  let icon: IconDefinition;
+
+  switch (status) {
+    case SecretSyncStatus.Failed:
+      variant = "danger";
+      text = "Failed to Sync";
+      icon = faExclamationTriangle;
+      break;
+    case SecretSyncStatus.Succeeded:
+      variant = "success";
+      text = "Synced";
+      icon = faCheck;
+      break;
+    case SecretSyncStatus.Pending: // no need to differentiate from user perspective
+    case SecretSyncStatus.Running:
+    default:
+      variant = "primary";
+      text = "Syncing";
+      icon = faRotate;
+      break;
+  }
+
+  return (
+    <Badge className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap" variant={variant}>
+      <FontAwesomeIcon icon={icon} />
+      <span>{text}</span>
+    </Badge>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/CreateSecretSyncForm.tsx b/frontend/src/components/secret-syncs/forms/CreateSecretSyncForm.tsx
new file mode 100644
index 0000000000..e7721f1131
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/CreateSecretSyncForm.tsx
@@ -0,0 +1,235 @@
+import { useState } from "react";
+import { Controller, FormProvider, useForm } from "react-hook-form";
+import { Tab } from "@headlessui/react";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { twMerge } from "tailwind-merge";
+
+import { createNotification } from "@app/components/notifications";
+import { Button, Checkbox, FormControl, Switch } from "@app/components/v2";
+import { useWorkspace } from "@app/context";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import {
+  SecretSync,
+  SecretSyncInitialSyncBehavior,
+  TSecretSync,
+  useCreateSecretSync,
+  useSecretSyncOption
+} from "@app/hooks/api/secretSyncs";
+
+import { SecretSyncFormSchema, TSecretSyncForm } from "./schemas";
+import { SecretSyncDestinationFields } from "./SecretSyncDestinationFields";
+import { SecretSyncDetailsFields } from "./SecretSyncDetailsFields";
+import { SecretSyncOptionsFields } from "./SecretSyncOptionsFields";
+import { SecretSyncReviewFields } from "./SecretSyncReviewFields";
+import { SecretSyncSourceFields } from "./SecretSyncSourceFields";
+
+type Props = {
+  onComplete: (secretSync: TSecretSync) => void;
+  destination: SecretSync;
+  onCancel: () => void;
+};
+
+const FORM_TABS: { name: string; key: string; fields: (keyof TSecretSyncForm)[] }[] = [
+  { name: "Source", key: "source", fields: ["secretPath", "environment"] },
+  { name: "Destination", key: "destination", fields: ["connection", "destinationConfig"] },
+  { name: "Options", key: "options", fields: ["syncOptions"] },
+  { name: "Details", key: "details", fields: ["name", "description"] },
+  { name: "Review", key: "review", fields: [] }
+];
+
+export const CreateSecretSyncForm = ({ destination, onComplete, onCancel }: Props) => {
+  const createSecretSync = useCreateSecretSync();
+  const { currentWorkspace } = useWorkspace();
+  const { name: destinationName } = SECRET_SYNC_MAP[destination];
+
+  const [selectedTabIndex, setSelectedTabIndex] = useState(0);
+  const [confirmOverwrite, setConfirmOverwrite] = useState(false);
+
+  const { syncOption } = useSecretSyncOption(destination);
+
+  const formMethods = useForm<TSecretSyncForm>({
+    resolver: zodResolver(SecretSyncFormSchema),
+    defaultValues: {
+      destination,
+      isAutoSyncEnabled: true,
+      syncOptions: {
+        initialSyncBehavior: syncOption?.canImportSecrets
+          ? undefined
+          : SecretSyncInitialSyncBehavior.OverwriteDestination
+      }
+    },
+    reValidateMode: "onChange"
+  });
+
+  const onSubmit = async ({ environment, connection, ...formData }: TSecretSyncForm) => {
+    try {
+      const secretSync = await createSecretSync.mutateAsync({
+        ...formData,
+        connectionId: connection.id,
+        environment: environment.slug,
+        projectId: currentWorkspace.id
+      });
+
+      createNotification({
+        text: `Successfully added ${destinationName} Sync`,
+        type: "success"
+      });
+      onComplete(secretSync);
+    } catch (err: any) {
+      console.error(err);
+      createNotification({
+        title: `Failed to add ${destinationName} Sync`,
+        text: err.message,
+        type: "error"
+      });
+    }
+  };
+
+  const handlePrev = () => {
+    if (selectedTabIndex === 0) {
+      onCancel();
+      return;
+    }
+
+    setSelectedTabIndex((prev) => prev - 1);
+  };
+
+  const { handleSubmit, trigger, watch, control } = formMethods;
+
+  const isStepValid = async (index: number) => trigger(FORM_TABS[index].fields);
+
+  const isFinalStep = selectedTabIndex === FORM_TABS.length - 1;
+
+  const handleNext = async () => {
+    if (isFinalStep) {
+      handleSubmit(onSubmit)();
+      return;
+    }
+
+    const isValid = await isStepValid(selectedTabIndex);
+
+    if (!isValid) return;
+
+    setSelectedTabIndex((prev) => prev + 1);
+  };
+
+  const isTabEnabled = async (index: number) => {
+    let isEnabled = true;
+    for (let i = index - 1; i >= 0; i -= 1) {
+      // eslint-disable-next-line no-await-in-loop
+      isEnabled = isEnabled && (await isStepValid(i));
+    }
+
+    return isEnabled;
+  };
+
+  const initialSyncBehavior = watch("syncOptions.initialSyncBehavior");
+
+  return (
+    <form className={twMerge(isFinalStep && "max-h-[70vh] overflow-y-auto")}>
+      <FormProvider {...formMethods}>
+        <Tab.Group selectedIndex={selectedTabIndex} onChange={setSelectedTabIndex}>
+          <Tab.List className="-pb-1 mb-6 w-full border-b-2 border-mineshaft-600">
+            {FORM_TABS.map((tab, index) => (
+              <Tab
+                onClick={async (e) => {
+                  e.preventDefault();
+                  const isEnabled = await isTabEnabled(index);
+                  setSelectedTabIndex((prev) => (isEnabled ? index : prev));
+                }}
+                className={({ selected }) =>
+                  `w-30 -mb-[0.14rem] ${index > selectedTabIndex ? "opacity-30" : ""} px-4 py-2 text-sm font-medium outline-none disabled:opacity-60 ${
+                    selected
+                      ? "border-b-2 border-mineshaft-300 text-mineshaft-200"
+                      : "text-bunker-300"
+                  }`
+                }
+                key={tab.key}
+              >
+                {index + 1}. {tab.name}
+              </Tab>
+            ))}
+          </Tab.List>
+          <Tab.Panels>
+            <Tab.Panel>
+              <SecretSyncSourceFields />
+            </Tab.Panel>
+            <Tab.Panel>
+              <SecretSyncDestinationFields />
+            </Tab.Panel>
+            <Tab.Panel>
+              <SecretSyncOptionsFields />
+              <Controller
+                control={control}
+                name="isAutoSyncEnabled"
+                render={({ field: { value, onChange }, fieldState: { error } }) => {
+                  return (
+                    <FormControl
+                      helperText={
+                        value
+                          ? "Secrets will automatically be synced when changes occur in the source location."
+                          : "Secrets will not automatically be synced when changes occur in the source location. You can still trigger syncs manually."
+                      }
+                      isError={Boolean(error)}
+                      errorText={error?.message}
+                    >
+                      <Switch
+                        className="bg-mineshaft-400/50 shadow-inner data-[state=checked]:bg-green/50"
+                        id="auto-sync-enabled"
+                        thumbClassName="bg-mineshaft-800"
+                        onCheckedChange={onChange}
+                        isChecked={value}
+                      >
+                        <p className="w-[8.4rem]">Auto-Sync {value ? "Enabled" : "Disabled"}</p>
+                      </Switch>
+                    </FormControl>
+                  );
+                }}
+              />
+            </Tab.Panel>
+            <Tab.Panel>
+              <SecretSyncDetailsFields />
+            </Tab.Panel>
+            <Tab.Panel>
+              <SecretSyncReviewFields />
+            </Tab.Panel>
+          </Tab.Panels>
+        </Tab.Group>
+      </FormProvider>
+      {isFinalStep &&
+        initialSyncBehavior === SecretSyncInitialSyncBehavior.OverwriteDestination && (
+          <Checkbox
+            id="confirm-overwrite"
+            isChecked={confirmOverwrite}
+            containerClassName="-mt-5"
+            onCheckedChange={(isChecked) => setConfirmOverwrite(Boolean(isChecked))}
+          >
+            <p
+              className={`mt-5 text-wrap text-xs ${confirmOverwrite ? "text-mineshaft-200" : "text-red"}`}
+            >
+              I understand all secrets present in the configured {destinationName} destination will
+              be removed if they are not present within Infisical.
+            </p>
+          </Checkbox>
+        )}
+      <div className="flex w-full flex-row-reverse justify-between gap-4 pt-4">
+        <Button
+          isDisabled={
+            isFinalStep &&
+            initialSyncBehavior === SecretSyncInitialSyncBehavior.OverwriteDestination &&
+            !confirmOverwrite
+          }
+          onClick={handleNext}
+          colorSchema="secondary"
+        >
+          {isFinalStep ? "Create Sync" : "Next"}
+        </Button>
+        {selectedTabIndex > 0 && (
+          <Button onClick={handlePrev} colorSchema="secondary">
+            Back
+          </Button>
+        )}
+      </div>
+    </form>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/EditSecretSyncForm.tsx b/frontend/src/components/secret-syncs/forms/EditSecretSyncForm.tsx
new file mode 100644
index 0000000000..d9306c671a
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/EditSecretSyncForm.tsx
@@ -0,0 +1,105 @@
+import { ReactNode } from "react";
+import { FormProvider, useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
+
+import { createNotification } from "@app/components/notifications";
+import { SecretSyncEditFields } from "@app/components/secret-syncs/types";
+import { Button, ModalClose } from "@app/components/v2";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { TSecretSync, useUpdateSecretSync } from "@app/hooks/api/secretSyncs";
+
+import { TSecretSyncForm, UpdateSecretSyncFormSchema } from "./schemas";
+import { SecretSyncDestinationFields } from "./SecretSyncDestinationFields";
+import { SecretSyncDetailsFields } from "./SecretSyncDetailsFields";
+import { SecretSyncOptionsFields } from "./SecretSyncOptionsFields";
+import { SecretSyncSourceFields } from "./SecretSyncSourceFields";
+
+type Props = {
+  onComplete: (secretSync: TSecretSync) => void;
+  secretSync: TSecretSync;
+  fields: SecretSyncEditFields;
+};
+
+export const EditSecretSyncForm = ({ secretSync, fields, onComplete }: Props) => {
+  const updateSecretSync = useUpdateSecretSync();
+  const { name: destinationName } = SECRET_SYNC_MAP[secretSync.destination];
+
+  const formMethods = useForm<TSecretSyncForm>({
+    resolver: zodResolver(UpdateSecretSyncFormSchema),
+    defaultValues: {
+      ...secretSync,
+      environment: secretSync.environment ?? undefined,
+      secretPath: secretSync.folder?.path,
+      description: secretSync.description ?? ""
+    },
+    reValidateMode: "onChange"
+  });
+
+  const onSubmit = async ({ environment, connection, ...formData }: TSecretSyncForm) => {
+    try {
+      const updatedSecretSync = await updateSecretSync.mutateAsync({
+        syncId: secretSync.id,
+        ...formData,
+        environment: environment?.slug,
+        connectionId: connection.id
+      });
+
+      createNotification({
+        text: `Successfully updated ${destinationName} Sync`,
+        type: "success"
+      });
+      onComplete(updatedSecretSync);
+    } catch (err: any) {
+      console.error(err);
+      createNotification({
+        title: `Failed to update ${destinationName} Sync`,
+        text: err.message,
+        type: "error"
+      });
+    }
+  };
+
+  let Component: ReactNode;
+
+  switch (fields) {
+    case SecretSyncEditFields.Destination:
+      Component = <SecretSyncDestinationFields />;
+      break;
+    case SecretSyncEditFields.Options:
+      Component = <SecretSyncOptionsFields hideInitialSync={Boolean(secretSync.lastSyncedAt)} />;
+      break;
+    case SecretSyncEditFields.Source:
+      Component = <SecretSyncSourceFields />;
+      break;
+    case SecretSyncEditFields.Details:
+    default:
+      Component = <SecretSyncDetailsFields />;
+      break;
+  }
+
+  const {
+    handleSubmit,
+    formState: { isSubmitting, isDirty }
+  } = formMethods;
+
+  return (
+    <form onSubmit={handleSubmit(onSubmit)}>
+      <FormProvider {...formMethods}>{Component}</FormProvider>
+      <div className="flex w-full justify-between gap-4 pt-4">
+        <ModalClose asChild>
+          <Button colorSchema="secondary" variant="plain">
+            Cancel
+          </Button>
+        </ModalClose>
+        <Button
+          isLoading={isSubmitting}
+          isDisabled={!isDirty || isSubmitting}
+          type="submit"
+          colorSchema="secondary"
+        >
+          Update Sync
+        </Button>
+      </div>
+    </form>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncConnectionField.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncConnectionField.tsx
new file mode 100644
index 0000000000..408e4af678
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncConnectionField.tsx
@@ -0,0 +1,90 @@
+import { Controller, useFormContext } from "react-hook-form";
+import { faInfoCircle } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Link } from "@tanstack/react-router";
+
+import { FilterableSelect, FormControl } from "@app/components/v2";
+import { OrgPermissionSubjects, useOrgPermission } from "@app/context";
+import { OrgPermissionAppConnectionActions } from "@app/context/OrgPermissionContext/types";
+import { APP_CONNECTION_MAP } from "@app/helpers/appConnections";
+import { SECRET_SYNC_CONNECTION_MAP } from "@app/helpers/secretSyncs";
+import { useListAvailableAppConnections } from "@app/hooks/api/appConnections";
+
+import { TSecretSyncForm } from "./schemas";
+
+type Props = {
+  onChange?: VoidFunction;
+};
+
+export const SecretSyncConnectionField = ({ onChange: callback }: Props) => {
+  const { permission } = useOrgPermission();
+  const { control, watch } = useFormContext<TSecretSyncForm>();
+
+  const destination = watch("destination");
+  const app = SECRET_SYNC_CONNECTION_MAP[destination];
+
+  const { data: options, isLoading } = useListAvailableAppConnections(app);
+
+  const connectionName = APP_CONNECTION_MAP[app].name;
+
+  const canCreateConnection = permission.can(
+    OrgPermissionAppConnectionActions.Create,
+    OrgPermissionSubjects.AppConnections
+  );
+
+  const appName = APP_CONNECTION_MAP[SECRET_SYNC_CONNECTION_MAP[destination]].name;
+
+  return (
+    <>
+      <p className="mb-4 text-sm text-bunker-300">
+        Specify the {appName} Connection to use to connect to {connectionName} and configure
+        destination parameters.
+      </p>
+      <Controller
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl
+            tooltipText="App Connections can be created from the Organization Settings page."
+            isError={Boolean(error)}
+            errorText={error?.message}
+            label={`${connectionName} Connection`}
+          >
+            <FilterableSelect
+              value={value}
+              onChange={(newValue) => {
+                onChange(newValue);
+                if (callback) callback();
+              }}
+              isLoading={isLoading}
+              options={options}
+              placeholder="Select connection..."
+              getOptionLabel={(option) => option.name}
+              getOptionValue={(option) => option.id}
+            />
+          </FormControl>
+        )}
+        control={control}
+        name="connection"
+      />
+      {options?.length === 0 && (
+        <p className="-mt-2.5 mb-2.5 text-xs text-yellow">
+          <FontAwesomeIcon className="mr-1" size="xs" icon={faInfoCircle} />
+          {canCreateConnection ? (
+            <>
+              You do not have access to any {appName} Connections. Create one from the{" "}
+              <Link
+                to="/organization/settings"
+                className="underline"
+                search={{ selectedTab: "app-connections" }}
+              >
+                Organization Settings
+              </Link>{" "}
+              page.
+            </>
+          ) : (
+            `You do not have access to any ${appName} Connections. Contact an admin to create one.`
+          )}
+        </p>
+      )}
+    </>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/AwsParameterStoreSyncFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/AwsParameterStoreSyncFields.tsx
new file mode 100644
index 0000000000..a77b0cc04b
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/AwsParameterStoreSyncFields.tsx
@@ -0,0 +1,67 @@
+import { Controller, useFormContext } from "react-hook-form";
+import { components, OptionProps, SingleValue } from "react-select";
+import { faCheckCircle } from "@fortawesome/free-regular-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/SecretSyncConnectionField";
+import { Badge, FilterableSelect, FormControl, Input } from "@app/components/v2";
+import { AWS_REGIONS } from "@app/helpers/appConnections";
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+
+import { TSecretSyncForm } from "../schemas";
+
+const Option = ({ isSelected, children, ...props }: OptionProps<(typeof AWS_REGIONS)[number]>) => {
+  return (
+    <components.Option isSelected={isSelected} {...props}>
+      <div className="flex flex-row items-center justify-between">
+        <p className="truncate">{children}</p>
+        <Badge variant="success" className="ml-1 mr-auto cursor-pointer">
+          {props.data.slug}
+        </Badge>
+        {isSelected && (
+          <FontAwesomeIcon className="ml-2 text-primary" icon={faCheckCircle} size="sm" />
+        )}
+      </div>
+    </components.Option>
+  );
+};
+
+export const AwsParameterStoreSyncFields = () => {
+  const { control } = useFormContext<
+    TSecretSyncForm & { destination: SecretSync.AWSParameterStore }
+  >();
+
+  return (
+    <>
+      <SecretSyncConnectionField />
+      <Controller
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl isError={Boolean(error)} errorText={error?.message} label="Region">
+            <FilterableSelect
+              value={AWS_REGIONS.find((region) => region.slug === value)}
+              onChange={(option) =>
+                onChange((option as SingleValue<(typeof AWS_REGIONS)[number]>)?.slug)
+              }
+              options={AWS_REGIONS}
+              placeholder="Select region..."
+              getOptionLabel={(option) => option.name}
+              getOptionValue={(option) => option.slug}
+              components={{ Option }}
+            />
+          </FormControl>
+        )}
+        control={control}
+        name="destinationConfig.region"
+      />
+      <Controller
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl isError={Boolean(error)} errorText={error?.message} label="Path">
+            <Input value={value} onChange={onChange} placeholder="Path..." />
+          </FormControl>
+        )}
+        control={control}
+        name="destinationConfig.path"
+      />
+    </>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/GitHubSyncFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/GitHubSyncFields.tsx
new file mode 100644
index 0000000000..cabda1e669
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/GitHubSyncFields.tsx
@@ -0,0 +1,231 @@
+import { Controller, useFormContext, useWatch } from "react-hook-form";
+import { MultiValue, SingleValue } from "react-select";
+
+import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/SecretSyncConnectionField";
+import { FilterableSelect, FormControl, Select, SelectItem } from "@app/components/v2";
+import {
+  TGitHubConnectionEnvironment,
+  TGitHubConnectionOrganization,
+  TGitHubConnectionRepository,
+  useGitHubConnectionListEnvironments,
+  useGitHubConnectionListOrganizations,
+  useGitHubConnectionListRepositories
+} from "@app/hooks/api/appConnections/github";
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+import {
+  GitHubSyncScope,
+  GitHubSyncVisibility
+} from "@app/hooks/api/secretSyncs/types/github-sync";
+
+import { TSecretSyncForm } from "../schemas";
+
+export const GitHubSyncFields = () => {
+  const { control, watch, setValue } = useFormContext<
+    TSecretSyncForm & { destination: SecretSync.GitHub }
+  >();
+
+  const connectionId = useWatch({ name: "connection.id", control });
+  const currentScope = watch("destinationConfig.scope");
+  const currentVisibility = watch("destinationConfig.visibility");
+  const currentOrg = watch("destinationConfig.org");
+  const currentRepo = watch("destinationConfig.repo");
+  const currentOwner = watch("destinationConfig.owner");
+
+  const { data: repositories = [], isPending: isRepositoriesPending } =
+    useGitHubConnectionListRepositories(connectionId, {
+      enabled: Boolean(connectionId)
+    });
+
+  const { data: organizations = [], isPending: isOrganizationsPending } =
+    useGitHubConnectionListOrganizations(connectionId, {
+      enabled: Boolean(connectionId && currentScope === GitHubSyncScope.Organization)
+    });
+
+  const { data: environments = [], isPending: isEnvironmentsPending } =
+    useGitHubConnectionListEnvironments(
+      {
+        connectionId,
+        repo: currentRepo,
+        owner: currentOwner
+      },
+      {
+        enabled: Boolean(
+          connectionId &&
+            currentRepo &&
+            currentOwner &&
+            currentScope === GitHubSyncScope.RepositoryEnvironment
+        )
+      }
+    );
+
+  return (
+    <>
+      <SecretSyncConnectionField
+        onChange={() => {
+          setValue("destinationConfig.org", "");
+          setValue("destinationConfig.repo", "");
+          setValue("destinationConfig.owner", "");
+          setValue("destinationConfig.selectedRepositoryIds", undefined);
+        }}
+      />
+      <Controller
+        name="destinationConfig.scope"
+        control={control}
+        defaultValue={GitHubSyncScope.Repository}
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl errorText={error?.message} isError={Boolean(error?.message)} label="Scope">
+            <Select
+              value={value}
+              onValueChange={(val) => {
+                onChange(val);
+              }}
+              className="w-full border border-mineshaft-500 capitalize"
+              position="popper"
+              placeholder="Select a scope..."
+              dropdownContainerClassName="max-w-none"
+            >
+              {Object.values(GitHubSyncScope).map((scope) => (
+                <SelectItem className="capitalize" value={scope} key={scope}>
+                  {scope.replace("-", " ")}
+                </SelectItem>
+              ))}
+            </Select>
+          </FormControl>
+        )}
+      />
+      {currentScope === GitHubSyncScope.Organization && (
+        <>
+          <Controller
+            name="destinationConfig.org"
+            control={control}
+            render={({ field: { value, onChange }, fieldState: { error } }) => (
+              <FormControl isError={Boolean(error)} errorText={error?.message} label="Organization">
+                <FilterableSelect
+                  isLoading={isOrganizationsPending && Boolean(connectionId)}
+                  isDisabled={!connectionId}
+                  value={organizations.find((org) => org.login === value) ?? null}
+                  onChange={(option) =>
+                    onChange((option as SingleValue<TGitHubConnectionOrganization>)?.login ?? null)
+                  }
+                  options={organizations}
+                  placeholder="Select an organization..."
+                  getOptionLabel={(option) => option.login}
+                  getOptionValue={(option) => option.login}
+                />
+              </FormControl>
+            )}
+          />
+          <Controller
+            name="destinationConfig.visibility"
+            control={control}
+            defaultValue={GitHubSyncVisibility.All}
+            render={({ field: { value, onChange }, fieldState: { error } }) => (
+              <FormControl
+                errorText={error?.message}
+                isError={Boolean(error?.message)}
+                label="Visibility"
+              >
+                <Select
+                  value={value}
+                  onValueChange={(val) => {
+                    onChange(val);
+                    setValue("destinationConfig.selectedRepositoryIds", undefined);
+                  }}
+                  className="w-full border border-mineshaft-500 capitalize"
+                  position="popper"
+                  placeholder="Select visibility..."
+                  dropdownContainerClassName="max-w-none"
+                >
+                  {Object.values(GitHubSyncVisibility).map((scope) => (
+                    <SelectItem className="capitalize" value={scope} key={scope}>
+                      {scope.replace("-", " ")} Repositories
+                    </SelectItem>
+                  ))}
+                </Select>
+              </FormControl>
+            )}
+          />
+          {currentVisibility === GitHubSyncVisibility.Selected && (
+            <Controller
+              render={({ field: { value, onChange }, fieldState: { error } }) => (
+                <FormControl
+                  isError={Boolean(error)}
+                  errorText={error?.message}
+                  label="Selected Repositories"
+                >
+                  <FilterableSelect
+                    menuPlacement="top"
+                    isLoading={isRepositoriesPending && Boolean(currentOrg)}
+                    isDisabled={!currentOrg || !connectionId}
+                    isMulti
+                    value={repositories.filter((repo) => value?.includes(repo.id))}
+                    onChange={(option) => {
+                      const repos = option as MultiValue<TGitHubConnectionRepository>;
+                      onChange(repos.map((repo) => repo.id));
+                    }}
+                    options={repositories.filter((repo) => repo.owner.login === currentOrg)}
+                    placeholder="Select one or more repositories..."
+                    getOptionLabel={(option) => `${option.owner.login}/${option.name}`}
+                    getOptionValue={(option) => option.id.toString()}
+                  />
+                </FormControl>
+              )}
+              control={control}
+              name="destinationConfig.selectedRepositoryIds"
+            />
+          )}
+        </>
+      )}
+      {currentScope !== GitHubSyncScope.Organization && (
+        <Controller
+          render={({ field: { value, onChange }, fieldState: { error } }) => (
+            <FormControl isError={Boolean(error)} errorText={error?.message} label="Repository">
+              <FilterableSelect
+                menuPlacement="top"
+                isLoading={isRepositoriesPending && Boolean(connectionId)}
+                isDisabled={!connectionId}
+                value={repositories.find((repo) => repo.name === value) ?? null}
+                onChange={(option) => {
+                  const repo = option as SingleValue<TGitHubConnectionRepository>;
+
+                  onChange(repo?.name);
+                  setValue("destinationConfig.owner", repo?.owner.login ?? "");
+                  setValue("destinationConfig.env", "");
+                }}
+                options={repositories}
+                placeholder="Select a repository..."
+                getOptionLabel={(option) => `${option.owner.login}/${option.name}`}
+                getOptionValue={(option) => option.id.toString()}
+              />
+            </FormControl>
+          )}
+          control={control}
+          name="destinationConfig.repo"
+        />
+      )}
+      {currentScope === GitHubSyncScope.RepositoryEnvironment && (
+        <Controller
+          name="destinationConfig.env"
+          control={control}
+          render={({ field: { value, onChange }, fieldState: { error } }) => (
+            <FormControl isError={Boolean(error)} errorText={error?.message} label="Environment">
+              <FilterableSelect
+                menuPlacement="top"
+                isLoading={isEnvironmentsPending && Boolean(connectionId) && Boolean(currentRepo)}
+                isDisabled={!connectionId || !currentRepo}
+                value={environments.find((env) => env.name === value) ?? null}
+                onChange={(option) =>
+                  onChange((option as SingleValue<TGitHubConnectionEnvironment>)?.name ?? null)
+                }
+                options={environments}
+                placeholder="Select an environment..."
+                getOptionLabel={(option) => option.name}
+                getOptionValue={(option) => option.id.toString()}
+              />
+            </FormControl>
+          )}
+        />
+      )}
+    </>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx
new file mode 100644
index 0000000000..8edca89fbf
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx
@@ -0,0 +1,22 @@
+import { useFormContext } from "react-hook-form";
+
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+
+import { TSecretSyncForm } from "../schemas";
+import { AwsParameterStoreSyncFields } from "./AwsParameterStoreSyncFields";
+import { GitHubSyncFields } from "./GitHubSyncFields";
+
+export const SecretSyncDestinationFields = () => {
+  const { watch } = useFormContext<TSecretSyncForm>();
+
+  const destination = watch("destination");
+
+  switch (destination) {
+    case SecretSync.AWSParameterStore:
+      return <AwsParameterStoreSyncFields />;
+    case SecretSync.GitHub:
+      return <GitHubSyncFields />;
+    default:
+      throw new Error(`Unhandled Destination Config Field: ${destination}`);
+  }
+};
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/index.ts b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/index.ts
new file mode 100644
index 0000000000..1d68e01c68
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/index.ts
@@ -0,0 +1 @@
+export * from "./SecretSyncDestinationFields";
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDetailsFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncDetailsFields.tsx
new file mode 100644
index 0000000000..8af512bfad
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncDetailsFields.tsx
@@ -0,0 +1,51 @@
+import { Controller, useFormContext } from "react-hook-form";
+
+import { FormControl, Input, TextArea } from "@app/components/v2";
+
+import { TSecretSyncForm } from "./schemas";
+
+export const SecretSyncDetailsFields = () => {
+  const { control } = useFormContext<TSecretSyncForm>();
+
+  return (
+    <>
+      <p className="mb-4 text-sm text-bunker-300">
+        Provide a name and description for this Secret Sync.
+      </p>
+      <Controller
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl
+            helperText="Must be slug-friendly"
+            isError={Boolean(error)}
+            errorText={error?.message}
+            label="Name"
+          >
+            <Input value={value} onChange={onChange} placeholder="my-secret-sync" />
+          </FormControl>
+        )}
+        control={control}
+        name="name"
+      />
+      <Controller
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl
+            isError={Boolean(error)}
+            isOptional
+            errorText={error?.message}
+            label="Description"
+          >
+            <TextArea
+              value={value}
+              onChange={onChange}
+              placeholder="Describe the purpose of this sync..."
+              className="!resize-none"
+              rows={4}
+            />
+          </FormControl>
+        )}
+        control={control}
+        name="description"
+      />
+    </>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields.tsx
new file mode 100644
index 0000000000..6bfef2f71d
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields.tsx
@@ -0,0 +1,124 @@
+import { Controller, useFormContext } from "react-hook-form";
+import { faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { FormControl, Select, SelectItem } from "@app/components/v2";
+import { SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP, SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { useSecretSyncOption } from "@app/hooks/api/secretSyncs";
+
+import { TSecretSyncForm } from "./schemas";
+
+type Props = {
+  hideInitialSync?: boolean;
+};
+
+export const SecretSyncOptionsFields = ({ hideInitialSync }: Props) => {
+  const { control, watch } = useFormContext<TSecretSyncForm>();
+
+  const destination = watch("destination");
+
+  const destinationName = SECRET_SYNC_MAP[destination].name;
+
+  const { syncOption } = useSecretSyncOption(destination);
+
+  return (
+    <>
+      <p className="mb-4 text-sm text-bunker-300">Configure how secrets should be synced.</p>
+      {!hideInitialSync && (
+        <>
+          <Controller
+            name="syncOptions.initialSyncBehavior"
+            control={control}
+            render={({ field: { value, onChange }, fieldState: { error } }) => (
+              <FormControl
+                tooltipClassName="max-w-lg py-3"
+                tooltipText={
+                  syncOption?.canImportSecrets ? (
+                    <div className="flex flex-col gap-3">
+                      <p>
+                        Specify how Infisical should resolve the initial sync to {destinationName}.
+                        The following options are available:
+                      </p>
+                      <ul className="flex list-disc flex-col gap-3 pl-4">
+                        {Object.values(SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP).map((details) => {
+                          const { name, description } = details(destinationName);
+
+                          return (
+                            <li key={name}>
+                              <p className="text-mineshaft-300">
+                                <span className="font-medium text-bunker-200">{name}</span>:{" "}
+                                {description}
+                              </p>
+                            </li>
+                          );
+                        })}
+                      </ul>
+                    </div>
+                  ) : undefined
+                }
+                errorText={error?.message}
+                isError={Boolean(error?.message)}
+                label="Initial Sync Behavior"
+              >
+                <Select
+                  isDisabled={!syncOption?.canImportSecrets}
+                  value={value}
+                  onValueChange={(val) => onChange(val)}
+                  className="w-full border border-mineshaft-500"
+                  position="popper"
+                  placeholder="Select an option..."
+                  dropdownContainerClassName="max-w-none"
+                >
+                  {Object.entries(SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP).map(([key, details]) => {
+                    const { name } = details(destinationName);
+
+                    return (
+                      <SelectItem value={key} key={key}>
+                        {name}
+                      </SelectItem>
+                    );
+                  })}
+                </Select>
+              </FormControl>
+            )}
+          />
+          {!syncOption?.canImportSecrets && (
+            <p className="-mt-2.5 mb-2.5 text-xs text-yellow">
+              <FontAwesomeIcon className="mr-1" size="xs" icon={faTriangleExclamation} />
+              {destinationName} only supports overwriting destination secrets. Secrets not present
+              in Infisical will be removed from the destination.
+            </p>
+          )}
+        </>
+      )}
+      {/* <Controller
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl
+            isError={Boolean(error)}
+            isOptional
+            errorText={error?.message}
+            label="Prepend Prefix"
+          >
+            <Input className="uppercase" value={value} onChange={onChange} placeholder="INF_" />
+          </FormControl>
+        )}
+        control={control}
+        name="syncOptions.prependPrefix"
+      />
+      <Controller
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl
+            isError={Boolean(error)}
+            isOptional
+            errorText={error?.message}
+            label="Append Suffix"
+          >
+            <Input className="uppercase" value={value} onChange={onChange} placeholder="_INF" />
+          </FormControl>
+        )}
+        control={control}
+        name="syncOptions.appendSuffix"
+      /> */}
+    </>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/AwsParameterStoreSyncReviewFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/AwsParameterStoreSyncReviewFields.tsx
new file mode 100644
index 0000000000..253cae69d6
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/AwsParameterStoreSyncReviewFields.tsx
@@ -0,0 +1,29 @@
+import { useFormContext } from "react-hook-form";
+
+import { SecretSyncLabel } from "@app/components/secret-syncs";
+import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas";
+import { Badge } from "@app/components/v2";
+import { AWS_REGIONS } from "@app/helpers/appConnections";
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+
+export const AwsParameterStoreSyncReviewFields = () => {
+  const { watch } = useFormContext<
+    TSecretSyncForm & { destination: SecretSync.AWSParameterStore }
+  >();
+
+  const [region, path] = watch(["destinationConfig.region", "destinationConfig.path"]);
+
+  const awsRegion = AWS_REGIONS.find((r) => r.slug === region);
+
+  return (
+    <>
+      <SecretSyncLabel label="Region">
+        {awsRegion?.name}
+        <Badge className="ml-1" variant="success">
+          {awsRegion?.slug}{" "}
+        </Badge>
+      </SecretSyncLabel>
+      <SecretSyncLabel label="Path">{path}</SecretSyncLabel>
+    </>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/GitHubSyncReviewFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/GitHubSyncReviewFields.tsx
new file mode 100644
index 0000000000..513a2762f6
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/GitHubSyncReviewFields.tsx
@@ -0,0 +1,61 @@
+import { ReactNode } from "react";
+import { useFormContext } from "react-hook-form";
+
+import { SecretSyncLabel } from "@app/components/secret-syncs";
+import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas";
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+import { GitHubSyncScope, TGitHubSync } from "@app/hooks/api/secretSyncs/types/github-sync";
+
+export const GitHubSyncReviewFields = () => {
+  const { watch } = useFormContext<TSecretSyncForm & { destination: SecretSync.GitHub }>();
+
+  const config = watch("destinationConfig");
+
+  let ScopeComponents: ReactNode;
+
+  switch (config.scope) {
+    case GitHubSyncScope.Repository:
+      ScopeComponents = (
+        <SecretSyncLabel label="Repository">
+          {config.owner}/{config.repo}
+        </SecretSyncLabel>
+      );
+      break;
+    case GitHubSyncScope.Organization:
+      ScopeComponents = (
+        <>
+          <SecretSyncLabel label="Organization">{config.org}</SecretSyncLabel>
+          <SecretSyncLabel className="capitalize" label="Visibility">
+            {config.visibility}
+          </SecretSyncLabel>
+        </>
+      );
+      break;
+    case GitHubSyncScope.RepositoryEnvironment:
+      ScopeComponents = (
+        <>
+          <SecretSyncLabel label="Repository">
+            {config.owner}/{config.repo}
+          </SecretSyncLabel>
+          <SecretSyncLabel className="capitalize" label="Environment">
+            {config.env}
+          </SecretSyncLabel>
+        </>
+      );
+
+      break;
+    default:
+      throw new Error(
+        `Unhandled GitHub Sync Review Field Scope ${(config as TGitHubSync["destinationConfig"]).scope}`
+      );
+  }
+
+  return (
+    <>
+      <SecretSyncLabel className="capitalize" label="Scope">
+        {config.scope.replace("-", " ")}
+      </SecretSyncLabel>
+      {ScopeComponents}
+    </>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx
new file mode 100644
index 0000000000..4b198eb7e5
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx
@@ -0,0 +1,93 @@
+import { ReactNode } from "react";
+import { useFormContext } from "react-hook-form";
+
+import { SecretSyncLabel } from "@app/components/secret-syncs";
+import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas";
+import { Badge } from "@app/components/v2";
+import { SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP, SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+
+import { AwsParameterStoreSyncReviewFields } from "./AwsParameterStoreSyncReviewFields";
+import { GitHubSyncReviewFields } from "./GitHubSyncReviewFields";
+
+export const SecretSyncReviewFields = () => {
+  const { watch } = useFormContext<TSecretSyncForm>();
+
+  let DestinationFieldsComponent: ReactNode;
+
+  const {
+    name,
+    description,
+    connection,
+    environment,
+    secretPath,
+    syncOptions: {
+      // appendSuffix, prependPrefix,
+      initialSyncBehavior
+    },
+    destination,
+    isAutoSyncEnabled
+  } = watch();
+
+  const destinationName = SECRET_SYNC_MAP[destination].name;
+
+  switch (destination) {
+    case SecretSync.AWSParameterStore:
+      DestinationFieldsComponent = <AwsParameterStoreSyncReviewFields />;
+      break;
+    case SecretSync.GitHub:
+      DestinationFieldsComponent = <GitHubSyncReviewFields />;
+      break;
+    default:
+      throw new Error(`Unhandled Destination Review Fields: ${destination}`);
+  }
+
+  return (
+    <div className="mb-4 flex flex-col gap-6">
+      <div className="flex flex-col gap-3">
+        <div className="w-full border-b border-mineshaft-600">
+          <span className="text-sm text-mineshaft-300">Source</span>
+        </div>
+        <div className="flex flex-wrap gap-x-8 gap-y-2">
+          <SecretSyncLabel label="Environment">{environment.name}</SecretSyncLabel>
+          <SecretSyncLabel label="Secret Path">{secretPath}</SecretSyncLabel>
+        </div>
+      </div>
+      <div className="flex flex-col gap-3">
+        <div className="w-full border-b border-mineshaft-600">
+          <span className="text-sm text-mineshaft-300">Destination</span>
+        </div>
+        <div className="flex flex-wrap gap-x-8 gap-y-2">
+          <SecretSyncLabel label="Connection">{connection.name}</SecretSyncLabel>
+          {DestinationFieldsComponent}
+        </div>
+      </div>
+      <div className="flex flex-col gap-3">
+        <div className="w-full border-b border-mineshaft-600">
+          <span className="text-sm text-mineshaft-300">Options</span>
+        </div>
+        <div className="flex flex-wrap gap-x-8 gap-y-2">
+          <SecretSyncLabel label="Auto-Sync">
+            <Badge variant={isAutoSyncEnabled ? "success" : "danger"}>
+              {isAutoSyncEnabled ? "Enabled" : "Disabled"}
+            </Badge>
+          </SecretSyncLabel>
+          <SecretSyncLabel label="Initial Sync Behavior">
+            {SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP[initialSyncBehavior](destinationName).name}
+          </SecretSyncLabel>
+          {/* <SecretSyncLabel label="Prepend Prefix">{prependPrefix}</SecretSyncLabel>
+          <SecretSyncLabel label="Append Suffix">{appendSuffix}</SecretSyncLabel> */}
+        </div>
+      </div>
+      <div className="flex flex-col gap-3">
+        <div className="w-full border-b border-mineshaft-600">
+          <span className="text-sm text-mineshaft-300">Details</span>
+        </div>
+        <div className="flex flex-wrap gap-x-8 gap-y-2">
+          <SecretSyncLabel label="Name">{name}</SecretSyncLabel>
+          <SecretSyncLabel label="Description">{description}</SecretSyncLabel>
+        </div>
+      </div>
+    </div>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/index.ts b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/index.ts
new file mode 100644
index 0000000000..3decaeddaf
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/index.ts
@@ -0,0 +1 @@
+export * from "./SecretSyncReviewFields";
diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncSourceFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncSourceFields.tsx
new file mode 100644
index 0000000000..7cc19ae971
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/SecretSyncSourceFields.tsx
@@ -0,0 +1,55 @@
+import { Controller, useFormContext } from "react-hook-form";
+
+import { FilterableSelect, FormControl } from "@app/components/v2";
+import { SecretPathInput } from "@app/components/v2/SecretPathInput";
+import { useWorkspace } from "@app/context";
+
+import { TSecretSyncForm } from "./schemas";
+
+export const SecretSyncSourceFields = () => {
+  const { control, watch } = useFormContext<TSecretSyncForm>();
+
+  const { currentWorkspace } = useWorkspace();
+
+  const selectedEnvironment = watch("environment");
+
+  return (
+    <>
+      <p className="mb-4 text-sm text-bunker-300">
+        Specify the environment and path where you would like to sync secrets from.
+      </p>
+
+      <Controller
+        defaultValue={currentWorkspace.environments[0]}
+        control={control}
+        name="environment"
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl label="Environment" isError={Boolean(error)} errorText={error?.message}>
+            <FilterableSelect
+              value={value}
+              onChange={onChange}
+              options={currentWorkspace.environments}
+              placeholder="Select environment..."
+              getOptionLabel={(option) => option?.name}
+              getOptionValue={(option) => option?.id}
+            />
+          </FormControl>
+        )}
+      />
+      <Controller
+        defaultValue="/"
+        render={({ field: { value, onChange }, fieldState: { error } }) => (
+          <FormControl isError={Boolean(error)} errorText={error?.message} label="Secret Path">
+            <SecretPathInput
+              environment={selectedEnvironment?.slug}
+              value={value}
+              onChange={onChange}
+            />
+          </FormControl>
+        )}
+        control={control}
+        name="secretPath"
+      />
+    </>
+  );
+};
diff --git a/frontend/src/components/secret-syncs/forms/index.ts b/frontend/src/components/secret-syncs/forms/index.ts
new file mode 100644
index 0000000000..a94aea6692
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/index.ts
@@ -0,0 +1,2 @@
+export * from "./CreateSecretSyncForm";
+export * from "./EditSecretSyncForm";
diff --git a/frontend/src/components/secret-syncs/forms/schemas/aws-parameter-store-sync-destination-schema.ts b/frontend/src/components/secret-syncs/forms/schemas/aws-parameter-store-sync-destination-schema.ts
new file mode 100644
index 0000000000..68abb77933
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/schemas/aws-parameter-store-sync-destination-schema.ts
@@ -0,0 +1,16 @@
+import { z } from "zod";
+
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+
+export const AwsParameterStoreSyncDestinationSchema = z.object({
+  destination: z.literal(SecretSync.AWSParameterStore),
+  destinationConfig: z.object({
+    path: z
+      .string()
+      .trim()
+      .min(1, "Parameter Store Path required")
+      .max(2048, "Cannot exceed 2048 characters")
+      .regex(/^\/([/]|(([\w-]+\/)+))?$/, 'Invalid path - must follow "/example/path/" format'),
+    region: z.string().min(1, "Region required")
+  })
+});
diff --git a/frontend/src/components/secret-syncs/forms/schemas/github-sync-destination-schema.ts b/frontend/src/components/secret-syncs/forms/schemas/github-sync-destination-schema.ts
new file mode 100644
index 0000000000..ccebc946c8
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/schemas/github-sync-destination-schema.ts
@@ -0,0 +1,45 @@
+import { z } from "zod";
+
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+import {
+  GitHubSyncScope,
+  GitHubSyncVisibility
+} from "@app/hooks/api/secretSyncs/types/github-sync";
+
+export const GitHubSyncDestinationSchema = z.object({
+  destination: z.literal(SecretSync.GitHub),
+  destinationConfig: z
+    .discriminatedUnion("scope", [
+      z.object({
+        scope: z.literal(GitHubSyncScope.Organization),
+        org: z.string().min(1, "Organization name required"),
+        visibility: z.nativeEnum(GitHubSyncVisibility),
+        selectedRepositoryIds: z.number().array().optional()
+      }),
+      z.object({
+        scope: z.literal(GitHubSyncScope.Repository),
+        owner: z.string().min(1, "Repository owner name required"),
+        repo: z.string().min(1, "Repository name required")
+      }),
+      z.object({
+        scope: z.literal(GitHubSyncScope.RepositoryEnvironment),
+        owner: z.string().min(1, "Repository owner name required"),
+        repo: z.string().min(1, "Repository name required"),
+        env: z.string().min(1, "Environment name required")
+      })
+    ])
+    .superRefine((options, ctx) => {
+      if (options.scope === GitHubSyncScope.Organization) {
+        if (
+          options.visibility === GitHubSyncVisibility.Selected &&
+          !options.selectedRepositoryIds?.length
+        ) {
+          ctx.addIssue({
+            code: z.ZodIssueCode.custom,
+            message: "Select at least 1 repository",
+            path: ["selectedRepositoryIds"]
+          });
+        }
+      }
+    })
+});
diff --git a/frontend/src/components/secret-syncs/forms/schemas/index.ts b/frontend/src/components/secret-syncs/forms/schemas/index.ts
new file mode 100644
index 0000000000..25c9c38d84
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/schemas/index.ts
@@ -0,0 +1 @@
+export * from "./secret-sync-schema";
diff --git a/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts b/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts
new file mode 100644
index 0000000000..2ae2bc3709
--- /dev/null
+++ b/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts
@@ -0,0 +1,41 @@
+import { z } from "zod";
+
+import { GitHubSyncDestinationSchema } from "@app/components/secret-syncs/forms/schemas/github-sync-destination-schema";
+import { SecretSyncInitialSyncBehavior } from "@app/hooks/api/secretSyncs";
+import { slugSchema } from "@app/lib/schemas";
+
+import { AwsParameterStoreSyncDestinationSchema } from "./aws-parameter-store-sync-destination-schema";
+
+const BaseSecretSyncSchema = z.object({
+  name: slugSchema({ field: "Name" }),
+  description: z.string().trim().max(256, "Cannot exceed 256 characters").optional(),
+  connection: z.object({ name: z.string(), id: z.string().uuid() }),
+  environment: z.object({ slug: z.string(), id: z.string(), name: z.string() }),
+  secretPath: z.string().min(1, "Secret path required"),
+  syncOptions: z.object({
+    initialSyncBehavior: z.nativeEnum(SecretSyncInitialSyncBehavior)
+    // scott: removed temporarily for evaluation of template formatting
+    // prependPrefix: z
+    //   .string()
+    //   .trim()
+    //   .transform((str) => str.toUpperCase())
+    //   .optional(),
+    // appendSuffix: z
+    //   .string()
+    //   .trim()
+    //   .transform((str) => str.toUpperCase())
+    //   .optional()
+  }),
+  isAutoSyncEnabled: z.boolean()
+});
+
+const SecretSyncUnionSchema = z.discriminatedUnion("destination", [
+  AwsParameterStoreSyncDestinationSchema,
+  GitHubSyncDestinationSchema
+]);
+
+export const SecretSyncFormSchema = SecretSyncUnionSchema.and(BaseSecretSyncSchema);
+
+export const UpdateSecretSyncFormSchema = SecretSyncUnionSchema.and(BaseSecretSyncSchema.partial());
+
+export type TSecretSyncForm = z.infer<typeof SecretSyncFormSchema>;
diff --git a/frontend/src/components/secret-syncs/github/GitHubSyncSelectedRepositoriesTooltipContent.tsx b/frontend/src/components/secret-syncs/github/GitHubSyncSelectedRepositoriesTooltipContent.tsx
new file mode 100644
index 0000000000..7e1876adac
--- /dev/null
+++ b/frontend/src/components/secret-syncs/github/GitHubSyncSelectedRepositoriesTooltipContent.tsx
@@ -0,0 +1,41 @@
+import { twMerge } from "tailwind-merge";
+
+import { useGitHubConnectionListRepositories } from "@app/hooks/api/appConnections/github";
+import { GitHubSyncScope, TGitHubSync } from "@app/hooks/api/secretSyncs/types/github-sync";
+
+type Props = {
+  secretSync: TGitHubSync;
+};
+
+export const GitHubSyncSelectedRepositoriesTooltipContent = ({ secretSync }: Props) => {
+  const { destinationConfig } = secretSync;
+
+  const showRepositories =
+    destinationConfig.scope === GitHubSyncScope.Organization &&
+    Boolean(destinationConfig.selectedRepositoryIds?.length);
+
+  const { data: repositories, isPending } = useGitHubConnectionListRepositories(
+    secretSync.connectionId,
+    {
+      enabled: showRepositories
+    }
+  );
+
+  if (destinationConfig.scope === GitHubSyncScope.Organization) {
+    return (
+      <>
+        <span className="text-xs text-bunker-300">Repositories:</span>
+        <p className={twMerge("text-sm", isPending && "text-mineshaft-400")}>
+          {isPending
+            ? "Loading..."
+            : repositories
+                ?.filter((repo) => destinationConfig?.selectedRepositoryIds?.includes(repo.id))
+                .map((repo) => repo.name)
+                .join(", ")}
+        </p>
+      </>
+    );
+  }
+
+  return null;
+};
diff --git a/frontend/src/components/secret-syncs/github/index.ts b/frontend/src/components/secret-syncs/github/index.ts
new file mode 100644
index 0000000000..df66220b33
--- /dev/null
+++ b/frontend/src/components/secret-syncs/github/index.ts
@@ -0,0 +1 @@
+export * from "./GitHubSyncSelectedRepositoriesTooltipContent";
diff --git a/frontend/src/components/secret-syncs/index.ts b/frontend/src/components/secret-syncs/index.ts
new file mode 100644
index 0000000000..74c1eeca36
--- /dev/null
+++ b/frontend/src/components/secret-syncs/index.ts
@@ -0,0 +1,9 @@
+export * from "./CreateSecretSyncModal";
+export * from "./DeleteSecretSyncModal";
+export * from "./EditSecretSyncModal";
+export * from "./SecretSyncImportSecretsModal";
+export * from "./SecretSyncImportStatusBadge";
+export * from "./SecretSyncLabel";
+export * from "./SecretSyncRemoveSecretsModal";
+export * from "./SecretSyncRemoveStatusBadge";
+export * from "./SecretSyncStatusBadge";
diff --git a/frontend/src/components/secret-syncs/types/index.ts b/frontend/src/components/secret-syncs/types/index.ts
new file mode 100644
index 0000000000..e016180b3e
--- /dev/null
+++ b/frontend/src/components/secret-syncs/types/index.ts
@@ -0,0 +1,6 @@
+export enum SecretSyncEditFields {
+  Details = "details",
+  Options = "options",
+  Source = "source",
+  Destination = "destination"
+}
diff --git a/frontend/src/components/v2/Modal/Modal.tsx b/frontend/src/components/v2/Modal/Modal.tsx
index 2ef6b81f7c..9b7baa9210 100644
--- a/frontend/src/components/v2/Modal/Modal.tsx
+++ b/frontend/src/components/v2/Modal/Modal.tsx
@@ -7,7 +7,7 @@ import { twMerge } from "tailwind-merge";
 import { Card, CardBody, CardFooter, CardTitle } from "../Card";
 import { IconButton } from "../IconButton";
 
-export type ModalContentProps = DialogPrimitive.DialogContentProps & {
+export type ModalContentProps = Omit<DialogPrimitive.DialogContentProps, "title"> & {
   title?: ReactNode;
   subTitle?: ReactNode;
   footerContent?: ReactNode;
diff --git a/frontend/src/components/v2/Switch/Switch.tsx b/frontend/src/components/v2/Switch/Switch.tsx
index ce955354ab..c781025982 100644
--- a/frontend/src/components/v2/Switch/Switch.tsx
+++ b/frontend/src/components/v2/Switch/Switch.tsx
@@ -9,6 +9,7 @@ export type SwitchProps = Omit<SwitchPrimitive.SwitchProps, "checked" | "disable
   isRequired?: boolean;
   isDisabled?: boolean;
   containerClassName?: string;
+  thumbClassName?: string;
 };
 
 export const Switch = ({
@@ -19,6 +20,7 @@ export const Switch = ({
   isDisabled,
   isRequired,
   containerClassName,
+  thumbClassName,
   ...props
 }: SwitchProps): JSX.Element => (
   <div className={twMerge("flex items-center font-inter text-bunker-300", containerClassName)}>
@@ -38,7 +40,12 @@ export const Switch = ({
       )}
       id={id}
     >
-      <SwitchPrimitive.Thumb className="block h-4 w-4 translate-x-0.5 rounded-full border-none bg-black shadow transition-all will-change-transform data-[state=checked]:translate-x-[18px]" />
+      <SwitchPrimitive.Thumb
+        className={twMerge(
+          "block h-4 w-4 translate-x-0.5 rounded-full border-none bg-black shadow transition-all will-change-transform data-[state=checked]:translate-x-[18px]",
+          thumbClassName
+        )}
+      />
     </SwitchPrimitive.Root>
   </div>
 );
diff --git a/frontend/src/const/routes.ts b/frontend/src/const/routes.ts
index 1ddec1377a..03e077a8de 100644
--- a/frontend/src/const/routes.ts
+++ b/frontend/src/const/routes.ts
@@ -64,10 +64,18 @@ export const ROUTE_PATHS = Object.freeze({
       "/secret-manager/$projectId/overview",
       "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/overview"
     ),
+    IntegrationsListPage: setRoute(
+      "/secret-manager/$projectId/integrations",
+      "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/"
+    ),
     IntegrationDetailsByIDPage: setRoute(
       "/secret-manager/$projectId/integrations/$integrationId",
       "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/$integrationId"
     ),
+    SecretSyncDetailsByIDPage: setRoute(
+      "/secret-manager/$projectId/integrations/secret-syncs/$destination/$syncId",
+      "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/secret-syncs/$destination/$syncId"
+    ),
     Integratons: {
       SelectIntegrationAuth: setRoute(
         "/secret-manager/$projectId/integrations/select-integration-auth",
diff --git a/frontend/src/context/OrgPermissionContext/types.ts b/frontend/src/context/OrgPermissionContext/types.ts
index 4480bbad82..ea5003c8ce 100644
--- a/frontend/src/context/OrgPermissionContext/types.ts
+++ b/frontend/src/context/OrgPermissionContext/types.ts
@@ -31,6 +31,18 @@ export enum OrgPermissionAdminConsoleAction {
   AccessAllProjects = "access-all-projects"
 }
 
+export enum OrgPermissionAppConnectionActions {
+  Read = "read",
+  Create = "create",
+  Edit = "edit",
+  Delete = "delete",
+  Connect = "connect"
+}
+
+export type AppConnectionSubjectFields = {
+  connectionId: string;
+};
+
 export type OrgPermissionSet =
   | [OrgPermissionActions.Create, OrgPermissionSubjects.Workspace]
   | [OrgPermissionActions.Read, OrgPermissionSubjects.Workspace]
@@ -49,6 +61,14 @@ export type OrgPermissionSet =
   | [OrgPermissionAdminConsoleAction, OrgPermissionSubjects.AdminConsole]
   | [OrgPermissionActions, OrgPermissionSubjects.AuditLogs]
   | [OrgPermissionActions, OrgPermissionSubjects.ProjectTemplates]
-  | [OrgPermissionActions, OrgPermissionSubjects.AppConnections];
+  | [OrgPermissionAppConnectionActions, OrgPermissionSubjects.AppConnections];
+// TODO(scott): add back once org UI refactored
+// | [
+//     OrgPermissionAppConnectionActions,
+//     (
+//       | OrgPermissionSubjects.AppConnections
+//       | (ForcedSubject<OrgPermissionSubjects.AppConnections> & AppConnectionSubjectFields)
+//     )
+//   ];
 
 export type TOrgPermission = MongoAbility<OrgPermissionSet>;
diff --git a/frontend/src/context/ProjectPermissionContext/types.ts b/frontend/src/context/ProjectPermissionContext/types.ts
index b0c3aa4637..279e69889a 100644
--- a/frontend/src/context/ProjectPermissionContext/types.ts
+++ b/frontend/src/context/ProjectPermissionContext/types.ts
@@ -24,6 +24,16 @@ export enum ProjectPermissionCmekActions {
   Decrypt = "decrypt"
 }
 
+export enum ProjectPermissionSecretSyncActions {
+  Read = "read",
+  Create = "create",
+  Edit = "edit",
+  Delete = "delete",
+  SyncSecrets = "sync-secrets",
+  ImportSecrets = "import-secrets",
+  RemoveSecrets = "remove-secrets"
+}
+
 export enum PermissionConditionOperators {
   $IN = "$in",
   $ALL = "$all",
@@ -91,7 +101,8 @@ export enum ProjectPermissionSub {
   PkiAlerts = "pki-alerts",
   PkiCollections = "pki-collections",
   Kms = "kms",
-  Cmek = "cmek"
+  Cmek = "cmek",
+  SecretSyncs = "secret-syncs"
 }
 
 export type SecretSubjectFields = {
@@ -173,6 +184,7 @@ export type ProjectPermissionSet =
   | [ProjectPermissionActions, ProjectPermissionSub.SshCertificates]
   | [ProjectPermissionActions, ProjectPermissionSub.PkiAlerts]
   | [ProjectPermissionActions, ProjectPermissionSub.PkiCollections]
+  | [ProjectPermissionSecretSyncActions, ProjectPermissionSub.SecretSyncs]
   | [ProjectPermissionActions.Delete, ProjectPermissionSub.Project]
   | [ProjectPermissionActions.Edit, ProjectPermissionSub.Project]
   | [ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback]
diff --git a/frontend/src/helpers/appConnections.ts b/frontend/src/helpers/appConnections.ts
index 9d52fb14e1..25551e3784 100644
--- a/frontend/src/helpers/appConnections.ts
+++ b/frontend/src/helpers/appConnections.ts
@@ -27,3 +27,35 @@ export const getAppConnectionMethodDetails = (method: TAppConnection["method"])
       throw new Error(`Unhandled App Connection Method: ${method}`);
   }
 };
+
+export const AWS_REGIONS = [
+  { name: "US East (Ohio)", slug: "us-east-2" },
+  { name: "US East (N. Virginia)", slug: "us-east-1" },
+  { name: "US West (N. California)", slug: "us-west-1" },
+  { name: "US West (Oregon)", slug: "us-west-2" },
+  { name: "Africa (Cape Town)", slug: "af-south-1" },
+  { name: "Asia Pacific (Hong Kong)", slug: "ap-east-1" },
+  { name: "Asia Pacific (Hyderabad)", slug: "ap-south-2" },
+  { name: "Asia Pacific (Jakarta)", slug: "ap-southeast-3" },
+  { name: "Asia Pacific (Melbourne)", slug: "ap-southeast-4" },
+  { name: "Asia Pacific (Mumbai)", slug: "ap-south-1" },
+  { name: "Asia Pacific (Osaka)", slug: "ap-northeast-3" },
+  { name: "Asia Pacific (Seoul)", slug: "ap-northeast-2" },
+  { name: "Asia Pacific (Singapore)", slug: "ap-southeast-1" },
+  { name: "Asia Pacific (Sydney)", slug: "ap-southeast-2" },
+  { name: "Asia Pacific (Tokyo)", slug: "ap-northeast-1" },
+  { name: "Canada (Central)", slug: "ca-central-1" },
+  { name: "Europe (Frankfurt)", slug: "eu-central-1" },
+  { name: "Europe (Ireland)", slug: "eu-west-1" },
+  { name: "Europe (London)", slug: "eu-west-2" },
+  { name: "Europe (Milan)", slug: "eu-south-1" },
+  { name: "Europe (Paris)", slug: "eu-west-3" },
+  { name: "Europe (Spain)", slug: "eu-south-2" },
+  { name: "Europe (Stockholm)", slug: "eu-north-1" },
+  { name: "Europe (Zurich)", slug: "eu-central-2" },
+  { name: "Middle East (Bahrain)", slug: "me-south-1" },
+  { name: "Middle East (UAE)", slug: "me-central-1" },
+  { name: "South America (Sao Paulo)", slug: "sa-east-1" },
+  { name: "AWS GovCloud (US-East)", slug: "us-gov-east-1" },
+  { name: "AWS GovCloud (US-West)", slug: "us-gov-west-1" }
+];
diff --git a/frontend/src/helpers/secretSyncs.ts b/frontend/src/helpers/secretSyncs.ts
new file mode 100644
index 0000000000..f46f0f2302
--- /dev/null
+++ b/frontend/src/helpers/secretSyncs.ts
@@ -0,0 +1,48 @@
+import { AppConnection } from "@app/hooks/api/appConnections/enums";
+import {
+  SecretSync,
+  SecretSyncImportBehavior,
+  SecretSyncInitialSyncBehavior
+} from "@app/hooks/api/secretSyncs";
+
+export const SECRET_SYNC_MAP: Record<SecretSync, { name: string; image: string }> = {
+  [SecretSync.AWSParameterStore]: { name: "Parameter Store", image: "Amazon Web Services.png" },
+  [SecretSync.GitHub]: { name: "GitHub", image: "GitHub.png" }
+};
+
+export const SECRET_SYNC_CONNECTION_MAP: Record<SecretSync, AppConnection> = {
+  [SecretSync.AWSParameterStore]: AppConnection.AWS,
+  [SecretSync.GitHub]: AppConnection.GitHub
+};
+
+export const SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP: Record<
+  SecretSyncInitialSyncBehavior,
+  (destinationName: string) => { name: string; description: string }
+> = {
+  [SecretSyncInitialSyncBehavior.OverwriteDestination]: (destinationName: string) => ({
+    name: "Overwrite Destination Secrets",
+    description: `Infisical will overwrite any secrets located in the ${destinationName} destination, removing any secrets that are not present within Infiscal. `
+  }),
+  [SecretSyncInitialSyncBehavior.ImportPrioritizeSource]: (destinationName: string) => ({
+    name: "Import Destination Secrets - Prioritize Infisical Values",
+    description: `Infisical will import any secrets present in the ${destinationName} destination prior to syncing, prioritizing values present in Infisical over ${destinationName}.`
+  }),
+  [SecretSyncInitialSyncBehavior.ImportPrioritizeDestination]: (destinationName: string) => ({
+    name: `Import Destination Secrets - Prioritize ${destinationName} Values`,
+    description: `Infisical will import any secrets present in the ${destinationName} destination prior to syncing, prioritizing values present in ${destinationName} over Infisical.`
+  })
+};
+
+export const SECRET_SYNC_IMPORT_BEHAVIOR_MAP: Record<
+  SecretSyncImportBehavior,
+  (destinationName: string) => { name: string; description: string }
+> = {
+  [SecretSyncImportBehavior.PrioritizeSource]: (destinationName: string) => ({
+    name: "Prioritize Infisical Values",
+    description: `Infisical will import any secrets present in the ${destinationName} destination, prioritizing values present in Infisical over ${destinationName}.`
+  }),
+  [SecretSyncImportBehavior.PrioritizeDestination]: (destinationName: string) => ({
+    name: `Prioritize ${destinationName} Values`,
+    description: `Infisical will import any secrets present in the ${destinationName} destination, prioritizing values present in ${destinationName} over Infisical.`
+  })
+};
diff --git a/frontend/src/hooks/api/appConnections/github/index.ts b/frontend/src/hooks/api/appConnections/github/index.ts
new file mode 100644
index 0000000000..2c1906d369
--- /dev/null
+++ b/frontend/src/hooks/api/appConnections/github/index.ts
@@ -0,0 +1,2 @@
+export * from "./queries";
+export * from "./types";
diff --git a/frontend/src/hooks/api/appConnections/github/queries.tsx b/frontend/src/hooks/api/appConnections/github/queries.tsx
new file mode 100644
index 0000000000..e042dc5e7d
--- /dev/null
+++ b/frontend/src/hooks/api/appConnections/github/queries.tsx
@@ -0,0 +1,105 @@
+import { useQuery, UseQueryOptions } from "@tanstack/react-query";
+
+import { apiRequest } from "@app/config/request";
+import { appConnectionKeys } from "@app/hooks/api/appConnections";
+
+import {
+  TGitHubConnectionEnvironment,
+  TGitHubConnectionListEnvironmentsResponse,
+  TGitHubConnectionListOrganizationsResponse,
+  TGitHubConnectionListRepositoriesResponse,
+  TGitHubConnectionOrganization,
+  TGitHubConnectionRepository,
+  TListGitHubConnectionEnvironments
+} from "./types";
+
+const githubConnectionKeys = {
+  all: [...appConnectionKeys.all, "github"] as const,
+  listRepositories: (connectionId: string) =>
+    [...githubConnectionKeys.all, "repositories", connectionId] as const,
+  listOrganizations: (connectionId: string) =>
+    [...githubConnectionKeys.all, "organizations", connectionId] as const,
+  listEnvironments: ({ connectionId, repo, owner }: TListGitHubConnectionEnvironments) =>
+    [...githubConnectionKeys.all, "environments", connectionId, repo, owner] as const
+};
+
+export const useGitHubConnectionListRepositories = (
+  connectionId: string,
+  options?: Omit<
+    UseQueryOptions<
+      TGitHubConnectionRepository[],
+      unknown,
+      TGitHubConnectionRepository[],
+      ReturnType<typeof githubConnectionKeys.listRepositories>
+    >,
+    "queryKey" | "queryFn"
+  >
+) => {
+  return useQuery({
+    queryKey: githubConnectionKeys.listRepositories(connectionId),
+    queryFn: async () => {
+      const { data } = await apiRequest.get<TGitHubConnectionListRepositoriesResponse>(
+        `/api/v1/app-connections/github/${connectionId}/repositories`
+      );
+
+      return data.repositories;
+    },
+    ...options
+  });
+};
+
+export const useGitHubConnectionListOrganizations = (
+  connectionId: string,
+  options?: Omit<
+    UseQueryOptions<
+      TGitHubConnectionOrganization[],
+      unknown,
+      TGitHubConnectionOrganization[],
+      ReturnType<typeof githubConnectionKeys.listOrganizations>
+    >,
+    "queryKey" | "queryFn"
+  >
+) => {
+  return useQuery({
+    queryKey: githubConnectionKeys.listOrganizations(connectionId),
+    queryFn: async () => {
+      const { data } = await apiRequest.get<TGitHubConnectionListOrganizationsResponse>(
+        `/api/v1/app-connections/github/${connectionId}/organizations`
+      );
+
+      return data.organizations;
+    },
+    ...options
+  });
+};
+
+export const useGitHubConnectionListEnvironments = (
+  { connectionId, repo, owner }: TListGitHubConnectionEnvironments,
+  options?: Omit<
+    UseQueryOptions<
+      TGitHubConnectionEnvironment[],
+      unknown,
+      TGitHubConnectionEnvironment[],
+      ReturnType<typeof githubConnectionKeys.listEnvironments>
+    >,
+    "queryKey" | "queryFn"
+  >
+) => {
+  return useQuery({
+    queryKey: githubConnectionKeys.listEnvironments({ connectionId, repo, owner }),
+    queryFn: async () => {
+      const { data } = await apiRequest.get<TGitHubConnectionListEnvironmentsResponse>(
+        `/api/v1/app-connections/github/${connectionId}/environments`,
+        {
+          params: {
+            repo,
+            owner
+          }
+        }
+      );
+
+      return data.environments;
+    },
+    ...options
+  });
+};
diff --git a/frontend/src/hooks/api/appConnections/github/types.ts b/frontend/src/hooks/api/appConnections/github/types.ts
new file mode 100644
index 0000000000..fab8ad7125
--- /dev/null
+++ b/frontend/src/hooks/api/appConnections/github/types.ts
@@ -0,0 +1,33 @@
+export type TGitHubConnectionOrganization = {
+  login: string;
+  id: number;
+};
+
+export type TGitHubConnectionRepository = {
+  id: number;
+  name: string;
+  owner: TGitHubConnectionOrganization;
+};
+
+export type TGitHubConnectionEnvironment = {
+  id: number;
+  name: string;
+};
+
+export type TGitHubConnectionListRepositoriesResponse = {
+  repositories: TGitHubConnectionRepository[];
+};
+
+export type TGitHubConnectionListOrganizationsResponse = {
+  organizations: TGitHubConnectionOrganization[];
+};
+
+export type TGitHubConnectionListEnvironmentsResponse = {
+  environments: TGitHubConnectionEnvironment[];
+};
+
+export type TListGitHubConnectionEnvironments = {
+  connectionId: string;
+  repo: string;
+  owner: string;
+};
diff --git a/frontend/src/hooks/api/appConnections/queries.tsx b/frontend/src/hooks/api/appConnections/queries.tsx
index e18c1facd3..981a8dbe12 100644
--- a/frontend/src/hooks/api/appConnections/queries.tsx
+++ b/frontend/src/hooks/api/appConnections/queries.tsx
@@ -7,6 +7,8 @@ import {
   TAppConnection,
   TAppConnectionMap,
   TAppConnectionOptions,
+  TAvailableAppConnection,
+  TAvailableAppConnectionsResponse,
   TGetAppConnection,
   TListAppConnections
 } from "@app/hooks/api/appConnections/types";
@@ -19,9 +21,10 @@ export const appConnectionKeys = {
   all: ["app-connection"] as const,
   options: () => [...appConnectionKeys.all, "options"] as const,
   list: () => [...appConnectionKeys.all, "list"] as const,
+  listAvailable: (app: AppConnection) => [...appConnectionKeys.all, app, "list-available"] as const,
   listByApp: (app: AppConnection) => [...appConnectionKeys.list(), app],
-  byId: (app: AppConnection, templateId: string) =>
-    [...appConnectionKeys.all, app, "by-id", templateId] as const
+  byId: (app: AppConnection, connectionId: string) =>
+    [...appConnectionKeys.all, app, "by-id", connectionId] as const
 };
 
 export const useAppConnectionOptions = (
@@ -83,6 +86,31 @@ export const useListAppConnections = (
   });
 };
 
+export const useListAvailableAppConnections = (
+  app: AppConnection,
+  options?: Omit<
+    UseQueryOptions<
+      TAvailableAppConnection[],
+      unknown,
+      TAvailableAppConnection[],
+      ReturnType<typeof appConnectionKeys.listAvailable>
+    >,
+    "queryKey" | "queryFn"
+  >
+) => {
+  return useQuery({
+    queryKey: appConnectionKeys.listAvailable(app),
+    queryFn: async () => {
+      const { data } = await apiRequest.get<TAvailableAppConnectionsResponse>(
+        `/api/v1/app-connections/${app}/available`
+      );
+
+      return data.appConnections;
+    },
+    ...options
+  });
+};
+
 export const useListAppConnectionsByApp = <T extends AppConnection>(
   app: T,
   options?: Omit<
diff --git a/frontend/src/hooks/api/appConnections/types/index.ts b/frontend/src/hooks/api/appConnections/types/index.ts
index fcec4a1df5..64bd41015f 100644
--- a/frontend/src/hooks/api/appConnections/types/index.ts
+++ b/frontend/src/hooks/api/appConnections/types/index.ts
@@ -8,10 +8,13 @@ export * from "./github-connection";
 
 export type TAppConnection = TAwsConnection | TGitHubConnection;
 
+export type TAvailableAppConnection = Pick<TAppConnection, "name" | "app" | "id">;
+
 export type TListAppConnections<T extends TAppConnection> = { appConnections: T[] };
 export type TGetAppConnection<T extends TAppConnection> = { appConnection: T };
 export type TAppConnectionOptions = { appConnectionOptions: TAppConnectionOption[] };
 export type TAppConnectionResponse = { appConnection: TAppConnection };
+export type TAvailableAppConnectionsResponse = { appConnections: TAvailableAppConnection[] };
 
 export type TCreateAppConnectionDTO = Pick<
   TAppConnection,
diff --git a/frontend/src/hooks/api/auditLogs/constants.tsx b/frontend/src/hooks/api/auditLogs/constants.tsx
index 650798bc7f..c736a564e8 100644
--- a/frontend/src/hooks/api/auditLogs/constants.tsx
+++ b/frontend/src/hooks/api/auditLogs/constants.tsx
@@ -85,7 +85,36 @@ export const eventToNameMap: { [K in EventType]: string } = {
   [EventType.INTEGRATION_SYNCED]: "Integration sync",
   [EventType.CREATE_SHARED_SECRET]: "Create shared secret",
   [EventType.DELETE_SHARED_SECRET]: "Delete shared secret",
-  [EventType.READ_SHARED_SECRET]: "Read shared secret"
+  [EventType.READ_SHARED_SECRET]: "Read shared secret",
+  [EventType.CREATE_CMEK]: "Create KMS key",
+  [EventType.UPDATE_CMEK]: "Update KMS key",
+  [EventType.DELETE_CMEK]: "Delete KMS key",
+  [EventType.GET_CMEKS]: "List KMS keys",
+  [EventType.CMEK_ENCRYPT]: "Encrypt with KMS key",
+  [EventType.CMEK_DECRYPT]: "Decrypt with KMS key",
+  [EventType.UPDATE_EXTERNAL_GROUP_ORG_ROLE_MAPPINGS]:
+    "Update SSO group to organization role mapping",
+  [EventType.GET_EXTERNAL_GROUP_ORG_ROLE_MAPPINGS]: "List SSO group to organization role mapping",
+  [EventType.GET_PROJECT_TEMPLATES]: "List project templates",
+  [EventType.GET_PROJECT_TEMPLATE]: "Get project template",
+  [EventType.CREATE_PROJECT_TEMPLATE]: "Create project template",
+  [EventType.UPDATE_PROJECT_TEMPLATE]: "Update project template",
+  [EventType.DELETE_PROJECT_TEMPLATE]: "Delete project template",
+  [EventType.APPLY_PROJECT_TEMPLATE]: "Apply project template",
+  [EventType.GET_APP_CONNECTIONS]: "List App Connections",
+  [EventType.GET_AVAILABLE_APP_CONNECTIONS_DETAILS]: "List App Connections Details",
+  [EventType.GET_APP_CONNECTION]: "Get App Connection",
+  [EventType.CREATE_APP_CONNECTION]: "Create App Connection",
+  [EventType.UPDATE_APP_CONNECTION]: "Update App Connection",
+  [EventType.DELETE_APP_CONNECTION]: "Delete App Connection",
+  [EventType.GET_SECRET_SYNCS]: "List Secret Syncs",
+  [EventType.GET_SECRET_SYNC]: "Get Secret Sync",
+  [EventType.CREATE_SECRET_SYNC]: "Create Secret Sync",
+  [EventType.UPDATE_SECRET_SYNC]: "Update Secret Sync",
+  [EventType.DELETE_SECRET_SYNC]: "Delete Secret Sync",
+  [EventType.SECRET_SYNC_SYNC_SECRETS]: "Secret Sync synced secrets",
+  [EventType.SECRET_SYNC_IMPORT_SECRETS]: "Secret Sync imported secrets",
+  [EventType.SECRET_SYNC_REMOVE_SECRETS]: "Secret Sync removed secrets"
 };
 
 export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = {
diff --git a/frontend/src/hooks/api/auditLogs/enums.tsx b/frontend/src/hooks/api/auditLogs/enums.tsx
index c2c306a965..7219a446ea 100644
--- a/frontend/src/hooks/api/auditLogs/enums.tsx
+++ b/frontend/src/hooks/api/auditLogs/enums.tsx
@@ -99,5 +99,33 @@ export enum EventType {
   INTEGRATION_SYNCED = "integration-synced",
   CREATE_SHARED_SECRET = "create-shared-secret",
   DELETE_SHARED_SECRET = "delete-shared-secret",
-  READ_SHARED_SECRET = "read-shared-secret"
+  READ_SHARED_SECRET = "read-shared-secret",
+  CREATE_CMEK = "create-cmek",
+  UPDATE_CMEK = "update-cmek",
+  DELETE_CMEK = "delete-cmek",
+  GET_CMEKS = "get-cmeks",
+  CMEK_ENCRYPT = "cmek-encrypt",
+  CMEK_DECRYPT = "cmek-decrypt",
+  UPDATE_EXTERNAL_GROUP_ORG_ROLE_MAPPINGS = "update-external-group-org-role-mapping",
+  GET_EXTERNAL_GROUP_ORG_ROLE_MAPPINGS = "get-external-group-org-role-mapping",
+  GET_PROJECT_TEMPLATES = "get-project-templates",
+  GET_PROJECT_TEMPLATE = "get-project-template",
+  CREATE_PROJECT_TEMPLATE = "create-project-template",
+  UPDATE_PROJECT_TEMPLATE = "update-project-template",
+  DELETE_PROJECT_TEMPLATE = "delete-project-template",
+  APPLY_PROJECT_TEMPLATE = "apply-project-template",
+  GET_APP_CONNECTIONS = "get-app-connections",
+  GET_AVAILABLE_APP_CONNECTIONS_DETAILS = "get-available-app-connections-details",
+  GET_APP_CONNECTION = "get-app-connection",
+  CREATE_APP_CONNECTION = "create-app-connection",
+  UPDATE_APP_CONNECTION = "update-app-connection",
+  DELETE_APP_CONNECTION = "delete-app-connection",
+  GET_SECRET_SYNCS = "get-secret-syncs",
+  GET_SECRET_SYNC = "get-secret-sync",
+  CREATE_SECRET_SYNC = "create-secret-sync",
+  UPDATE_SECRET_SYNC = "update-secret-sync",
+  DELETE_SECRET_SYNC = "delete-secret-sync",
+  SECRET_SYNC_SYNC_SECRETS = "secret-sync-sync-secrets",
+  SECRET_SYNC_IMPORT_SECRETS = "secret-sync-import-secrets",
+  SECRET_SYNC_REMOVE_SECRETS = "secret-sync-remove-secrets"
 }
diff --git a/frontend/src/hooks/api/reactQuery.tsx b/frontend/src/hooks/api/reactQuery.tsx
index 095ad1a7aa..d6ffc93785 100644
--- a/frontend/src/hooks/api/reactQuery.tsx
+++ b/frontend/src/hooks/api/reactQuery.tsx
@@ -182,7 +182,7 @@ export const queryClient = new QueryClient({
         createNotification({
           title: "Bad Request",
           type: "error",
-          text: `${serverResponse.message}.`,
+          text: `${serverResponse.message}${serverResponse.message.endsWith(".") ? "" : "."}`,
           copyActions: [
             {
               value: serverResponse.reqId,
diff --git a/frontend/src/hooks/api/secretSyncs/enums.ts b/frontend/src/hooks/api/secretSyncs/enums.ts
new file mode 100644
index 0000000000..b5211eedc0
--- /dev/null
+++ b/frontend/src/hooks/api/secretSyncs/enums.ts
@@ -0,0 +1,22 @@
+export enum SecretSync {
+  AWSParameterStore = "aws-parameter-store",
+  GitHub = "github"
+}
+
+export enum SecretSyncStatus {
+  Pending = "pending",
+  Running = "running",
+  Succeeded = "succeeded",
+  Failed = "failed"
+}
+
+export enum SecretSyncInitialSyncBehavior {
+  OverwriteDestination = "overwrite-destination",
+  ImportPrioritizeSource = "import-prioritize-source",
+  ImportPrioritizeDestination = "import-prioritize-destination"
+}
+
+export enum SecretSyncImportBehavior {
+  PrioritizeSource = "prioritize-source",
+  PrioritizeDestination = "prioritize-destination"
+}
diff --git a/frontend/src/hooks/api/secretSyncs/index.ts b/frontend/src/hooks/api/secretSyncs/index.ts
new file mode 100644
index 0000000000..f49a872a5a
--- /dev/null
+++ b/frontend/src/hooks/api/secretSyncs/index.ts
@@ -0,0 +1,4 @@
+export * from "./enums";
+export * from "./mutations";
+export * from "./queries";
+export * from "./types";
diff --git a/frontend/src/hooks/api/secretSyncs/mutations.tsx b/frontend/src/hooks/api/secretSyncs/mutations.tsx
new file mode 100644
index 0000000000..1efab66886
--- /dev/null
+++ b/frontend/src/hooks/api/secretSyncs/mutations.tsx
@@ -0,0 +1,118 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query";
+
+import { apiRequest } from "@app/config/request";
+import { secretSyncKeys } from "@app/hooks/api/secretSyncs/queries";
+import {
+  TCreateSecretSyncDTO,
+  TDeleteSecretSyncDTO,
+  TSecretSyncResponse,
+  TTriggerSecretSyncImportSecretsDTO,
+  TTriggerSecretSyncRemoveSecretsDTO,
+  TTriggerSecretSyncSyncSecretsDTO,
+  TUpdateSecretSyncDTO
+} from "@app/hooks/api/secretSyncs/types";
+
+export const useCreateSecretSync = () => {
+  const queryClient = useQueryClient();
+  return useMutation({
+    mutationFn: async ({ destination, ...params }: TCreateSecretSyncDTO) => {
+      const { data } = await apiRequest.post<TSecretSyncResponse>(
+        `/api/v1/secret-syncs/${destination}`,
+        params
+      );
+
+      return data.secretSync;
+    },
+    onSuccess: () => queryClient.invalidateQueries({ queryKey: secretSyncKeys.list() })
+  });
+};
+
+export const useUpdateSecretSync = () => {
+  const queryClient = useQueryClient();
+  return useMutation({
+    mutationFn: async ({ syncId, destination, ...params }: TUpdateSecretSyncDTO) => {
+      const { data } = await apiRequest.patch<TSecretSyncResponse>(
+        `/api/v1/secret-syncs/${destination}/${syncId}`,
+        params
+      );
+
+      return data.secretSync;
+    },
+    onSuccess: (_, { syncId, destination }) => {
+      queryClient.invalidateQueries({ queryKey: secretSyncKeys.list() });
+      queryClient.invalidateQueries({ queryKey: secretSyncKeys.byId(destination, syncId) });
+    }
+  });
+};
+
+export const useDeleteSecretSync = () => {
+  const queryClient = useQueryClient();
+  return useMutation({
+    mutationFn: async ({ syncId, destination, removeSecrets }: TDeleteSecretSyncDTO) => {
+      const { data } = await apiRequest.delete(`/api/v1/secret-syncs/${destination}/${syncId}`, {
+        params: { removeSecrets }
+      });
+
+      return data;
+    },
+    onSuccess: (_, { syncId, destination }) => {
+      queryClient.invalidateQueries({ queryKey: secretSyncKeys.list() });
+      queryClient.invalidateQueries({ queryKey: secretSyncKeys.byId(destination, syncId) });
+    }
+  });
+};
+
+export const useTriggerSecretSyncSyncSecrets = () => {
+  const queryClient = useQueryClient();
+  return useMutation({
+    mutationFn: async ({ syncId, destination }: TTriggerSecretSyncSyncSecretsDTO) => {
+      const { data } = await apiRequest.post(
+        `/api/v1/secret-syncs/${destination}/${syncId}/sync-secrets`
+      );
+
+      return data;
+    },
+    onSuccess: (_, { syncId, destination }) => {
+      queryClient.invalidateQueries({ queryKey: secretSyncKeys.list() });
+      queryClient.invalidateQueries({ queryKey: secretSyncKeys.byId(destination, syncId) });
+    }
+  });
+};
+
+export const useTriggerSecretSyncImportSecrets = () => {
+  const queryClient = useQueryClient();
+  return useMutation({
+    mutationFn: async ({
+      syncId,
+      destination,
+      importBehavior
+    }: TTriggerSecretSyncImportSecretsDTO) => {
+      const { data } = await apiRequest.post(
+        `/api/v1/secret-syncs/${destination}/${syncId}/import-secrets?importBehavior=${importBehavior}`
+      );
+
+      return data;
+    },
+    onSuccess: (_, { syncId, destination }) => {
+      queryClient.invalidateQueries({ queryKey: secretSyncKeys.list() });
+      queryClient.invalidateQueries({ queryKey: secretSyncKeys.byId(destination, syncId) });
+    }
+  });
+};
+
+export const useTriggerSecretSyncRemoveSecrets = () => {
+  const queryClient = useQueryClient();
+  return useMutation({
+    mutationFn: async ({ syncId, destination }: TTriggerSecretSyncRemoveSecretsDTO) => {
+      const { data } = await apiRequest.post(
+        `/api/v1/secret-syncs/${destination}/${syncId}/remove-secrets`
+      );
+
+      return data;
+    },
+    onSuccess: (_, { syncId, destination }) => {
+      queryClient.invalidateQueries({ queryKey: secretSyncKeys.list() });
+      queryClient.invalidateQueries({ queryKey: secretSyncKeys.byId(destination, syncId) });
+    }
+  });
+};
diff --git a/frontend/src/hooks/api/secretSyncs/queries.tsx b/frontend/src/hooks/api/secretSyncs/queries.tsx
new file mode 100644
index 0000000000..dbf444e202
--- /dev/null
+++ b/frontend/src/hooks/api/secretSyncs/queries.tsx
@@ -0,0 +1,88 @@
+import { useQuery, UseQueryOptions } from "@tanstack/react-query";
+
+import { apiRequest } from "@app/config/request";
+import { SecretSync, TSecretSyncOption } from "@app/hooks/api/secretSyncs";
+import {
+  TListSecretSyncOptions,
+  TListSecretSyncs,
+  TSecretSync,
+  TSecretSyncResponse
+} from "@app/hooks/api/secretSyncs/types";
+
+export const secretSyncKeys = {
+  all: ["secret-sync"] as const,
+  options: () => [...secretSyncKeys.all, "options"] as const,
+  list: () => [...secretSyncKeys.all, "list"] as const,
+  byId: (destination: SecretSync, syncId: string) =>
+    [...secretSyncKeys.all, destination, "by-id", syncId] as const
+};
+
+export const useSecretSyncOptions = (
+  options?: Omit<
+    UseQueryOptions<
+      TSecretSyncOption[],
+      unknown,
+      TSecretSyncOption[],
+      ReturnType<typeof secretSyncKeys.options>
+    >,
+    "queryKey" | "queryFn"
+  >
+) => {
+  return useQuery({
+    queryKey: secretSyncKeys.options(),
+    queryFn: async () => {
+      const { data } = await apiRequest.get<TListSecretSyncOptions>("/api/v1/secret-syncs/options");
+
+      return data.secretSyncOptions;
+    },
+    ...options
+  });
+};
+
+export const useSecretSyncOption = (destination: SecretSync) => {
+  const { data: syncOptions, isPending } = useSecretSyncOptions();
+  const syncOption = syncOptions?.find((option) => option.destination === destination);
+
+  return { syncOption, isPending };
+};
+
+export const useListSecretSyncs = (
+  projectId: string,
+  options?: Omit<
+    UseQueryOptions<TSecretSync[], unknown, TSecretSync[], ReturnType<typeof secretSyncKeys.list>>,
+    "queryKey" | "queryFn"
+  >
+) => {
+  return useQuery({
+    queryKey: secretSyncKeys.list(),
+    queryFn: async () => {
+      const { data } = await apiRequest.get<TListSecretSyncs>("/api/v1/secret-syncs", {
+        params: { projectId }
+      });
+
+      return data.secretSyncs;
+    },
+    ...options
+  });
+};
+
+export const useGetSecretSync = (
+  destination: SecretSync,
+  syncId: string,
+  options?: Omit<
+    UseQueryOptions<TSecretSync, unknown, TSecretSync, ReturnType<typeof secretSyncKeys.byId>>,
+    "queryKey" | "queryFn"
+  >
+) => {
+  return useQuery({
+    queryKey: secretSyncKeys.byId(destination, syncId),
+    queryFn: async () => {
+      const { data } = await apiRequest.get<TSecretSyncResponse>(
+        `/api/v1/secret-syncs/${destination}/${syncId}`
+      );
+
+      return data.secretSync;
+    },
+    ...options
+  });
+};
diff --git a/frontend/src/hooks/api/secretSyncs/types/aws-parameter-store-sync.ts b/frontend/src/hooks/api/secretSyncs/types/aws-parameter-store-sync.ts
new file mode 100644
index 0000000000..26c7aed686
--- /dev/null
+++ b/frontend/src/hooks/api/secretSyncs/types/aws-parameter-store-sync.ts
@@ -0,0 +1,16 @@
+import { AppConnection } from "@app/hooks/api/appConnections/enums";
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+import { TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync";
+
+export type TAwsParameterStoreSync = TRootSecretSync & {
+  destination: SecretSync.AWSParameterStore;
+  destinationConfig: {
+    path: string;
+    region: string;
+  };
+  connection: {
+    app: AppConnection.AWS;
+    name: string;
+    id: string;
+  };
+};
diff --git a/frontend/src/hooks/api/secretSyncs/types/github-sync.ts b/frontend/src/hooks/api/secretSyncs/types/github-sync.ts
new file mode 100644
index 0000000000..8bb18be47d
--- /dev/null
+++ b/frontend/src/hooks/api/secretSyncs/types/github-sync.ts
@@ -0,0 +1,42 @@
+import { AppConnection } from "@app/hooks/api/appConnections/enums";
+import { SecretSync } from "@app/hooks/api/secretSyncs";
+import { TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync";
+
+export enum GitHubSyncScope {
+  Organization = "organization",
+  Repository = "repository",
+  RepositoryEnvironment = "repository-environment"
+}
+
+export enum GitHubSyncVisibility {
+  All = "all",
+  Private = "private",
+  Selected = "selected"
+}
+
+export type TGitHubSync = TRootSecretSync & {
+  destination: SecretSync.GitHub;
+  destinationConfig:
+    | {
+        scope: GitHubSyncScope.Organization;
+        org: string;
+        visibility: GitHubSyncVisibility;
+        selectedRepositoryIds?: number[];
+      }
+    | {
+        scope: GitHubSyncScope.Repository;
+        owner: string;
+        repo: string;
+      }
+    | {
+        scope: GitHubSyncScope.RepositoryEnvironment;
+        owner: string;
+        repo: string;
+        env: string;
+      };
+  connection: {
+    app: AppConnection.GitHub;
+    name: string;
+    id: string;
+  };
+};
diff --git a/frontend/src/hooks/api/secretSyncs/types/index.ts b/frontend/src/hooks/api/secretSyncs/types/index.ts
new file mode 100644
index 0000000000..c0b7143214
--- /dev/null
+++ b/frontend/src/hooks/api/secretSyncs/types/index.ts
@@ -0,0 +1,57 @@
+import { SecretSync, SecretSyncImportBehavior } from "@app/hooks/api/secretSyncs";
+import { TAwsParameterStoreSync } from "@app/hooks/api/secretSyncs/types/aws-parameter-store-sync";
+import { TGitHubSync } from "@app/hooks/api/secretSyncs/types/github-sync";
+import { DiscriminativePick } from "@app/types";
+
+export type TSecretSyncOption = {
+  name: string;
+  destination: SecretSync;
+  canImportSecrets: boolean;
+};
+
+export type TSecretSync = TAwsParameterStoreSync | TGitHubSync;
+
+export type TListSecretSyncs = { secretSyncs: TSecretSync[] };
+
+export type TListSecretSyncOptions = { secretSyncOptions: TSecretSyncOption[] };
+export type TSecretSyncResponse = { secretSync: TSecretSync };
+
+export type TCreateSecretSyncDTO = DiscriminativePick<
+  TSecretSync,
+  | "name"
+  | "destinationConfig"
+  | "description"
+  | "connectionId"
+  | "syncOptions"
+  | "destination"
+  | "isAutoSyncEnabled"
+> & { environment: string; secretPath: string; projectId: string };
+
+export type TUpdateSecretSyncDTO = Partial<
+  Omit<TCreateSecretSyncDTO, "destination" | "projectId">
+> & {
+  destination: SecretSync;
+  syncId: string;
+};
+
+export type TDeleteSecretSyncDTO = {
+  destination: SecretSync;
+  syncId: string;
+  removeSecrets: boolean;
+};
+
+export type TTriggerSecretSyncSyncSecretsDTO = {
+  destination: SecretSync;
+  syncId: string;
+};
+
+export type TTriggerSecretSyncImportSecretsDTO = {
+  destination: SecretSync;
+  syncId: string;
+  importBehavior: SecretSyncImportBehavior;
+};
+
+export type TTriggerSecretSyncRemoveSecretsDTO = {
+  destination: SecretSync;
+  syncId: string;
+};
diff --git a/frontend/src/hooks/api/secretSyncs/types/root-sync.ts b/frontend/src/hooks/api/secretSyncs/types/root-sync.ts
new file mode 100644
index 0000000000..947b58e4af
--- /dev/null
+++ b/frontend/src/hooks/api/secretSyncs/types/root-sync.ts
@@ -0,0 +1,46 @@
+import { AppConnection } from "@app/hooks/api/appConnections/enums";
+import { SecretSyncInitialSyncBehavior, SecretSyncStatus } from "@app/hooks/api/secretSyncs";
+
+export type TRootSecretSync = {
+  id: string;
+  name: string;
+  description?: string | null;
+  version: number;
+  folderId: string | null;
+  connectionId: string;
+  createdAt: string;
+  updatedAt: string;
+  isAutoSyncEnabled: boolean;
+  projectId: string;
+  syncStatus: SecretSyncStatus | null;
+  lastSyncJobId: string | null;
+  lastSyncedAt: Date | null;
+  lastSyncMessage: string | null;
+  importStatus: SecretSyncStatus | null;
+  lastImportJobId: string | null;
+  lastImportedAt: Date | null;
+  lastImportMessage: string | null;
+  removeStatus: SecretSyncStatus | null;
+  lastRemoveJobId: string | null;
+  lastRemovedAt: Date | null;
+  lastRemoveMessage: string | null;
+  syncOptions: {
+    initialSyncBehavior: SecretSyncInitialSyncBehavior;
+    // prependPrefix?: string;
+    // appendSuffix?: string;
+  };
+  connection: {
+    app: AppConnection;
+    id: string;
+    name: string;
+  };
+  environment: {
+    id: string;
+    name: string;
+    slug: string;
+  } | null;
+  folder: {
+    id: string;
+    path: string;
+  } | null;
+};
diff --git a/frontend/src/hooks/api/subscriptions/types.ts b/frontend/src/hooks/api/subscriptions/types.ts
index 5ad3c42217..c67b3f8c34 100644
--- a/frontend/src/hooks/api/subscriptions/types.ts
+++ b/frontend/src/hooks/api/subscriptions/types.ts
@@ -46,5 +46,4 @@ export type SubscriptionPlan = {
   pkiEst: boolean;
   enforceMfa: boolean;
   projectTemplates: boolean;
-  appConnections: boolean;
 };
diff --git a/frontend/src/pages/organization/AppConnections/GithubOauthCallbackPage/GithubOauthCallbackPage.tsx b/frontend/src/pages/organization/AppConnections/GithubOauthCallbackPage/GithubOauthCallbackPage.tsx
index 2370daa95e..a71bb17443 100644
--- a/frontend/src/pages/organization/AppConnections/GithubOauthCallbackPage/GithubOauthCallbackPage.tsx
+++ b/frontend/src/pages/organization/AppConnections/GithubOauthCallbackPage/GithubOauthCallbackPage.tsx
@@ -44,11 +44,6 @@ export const GitHubOAuthCallbackPage = () => {
 
       // validate state
       if (state !== localStorage.getItem("latestCSRFToken")) {
-        createNotification({
-          type: "error",
-          text: "Invalid state, redirecting..."
-        });
-        navigate({ to: "/" });
         return;
       }
 
diff --git a/frontend/src/pages/organization/RoleByIDPage/components/OrgRoleModifySection.utils.ts b/frontend/src/pages/organization/RoleByIDPage/components/OrgRoleModifySection.utils.ts
index 56f922b52e..5b73bcf77f 100644
--- a/frontend/src/pages/organization/RoleByIDPage/components/OrgRoleModifySection.utils.ts
+++ b/frontend/src/pages/organization/RoleByIDPage/components/OrgRoleModifySection.utils.ts
@@ -2,6 +2,7 @@
 import { z } from "zod";
 
 import { OrgPermissionSubjects } from "@app/context";
+import { OrgPermissionAppConnectionActions } from "@app/context/OrgPermissionContext/types";
 import { TPermission } from "@app/hooks/api/roles/types";
 
 const generalPermissionSchema = z
@@ -13,6 +14,16 @@ const generalPermissionSchema = z
   })
   .optional();
 
+const appConnectionsPermissionSchema = z
+  .object({
+    [OrgPermissionAppConnectionActions.Read]: z.boolean().optional(),
+    [OrgPermissionAppConnectionActions.Edit]: z.boolean().optional(),
+    [OrgPermissionAppConnectionActions.Create]: z.boolean().optional(),
+    [OrgPermissionAppConnectionActions.Delete]: z.boolean().optional(),
+    [OrgPermissionAppConnectionActions.Connect]: z.boolean().optional()
+  })
+  .optional();
+
 const adminConsolePermissionSchmea = z
   .object({
     "access-all-projects": z.boolean().optional()
@@ -50,7 +61,7 @@ export const formSchema = z.object({
       "organization-admin-console": adminConsolePermissionSchmea,
       [OrgPermissionSubjects.Kms]: generalPermissionSchema,
       [OrgPermissionSubjects.ProjectTemplates]: generalPermissionSchema,
-      [OrgPermissionSubjects.AppConnections]: generalPermissionSchema
+      "app-connections": appConnectionsPermissionSchema
     })
     .optional()
 });
diff --git a/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/OrgPermissionAppConnectionRow.tsx b/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/OrgPermissionAppConnectionRow.tsx
new file mode 100644
index 0000000000..7a5cb25c74
--- /dev/null
+++ b/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/OrgPermissionAppConnectionRow.tsx
@@ -0,0 +1,186 @@
+import { useEffect, useMemo } from "react";
+import { Control, Controller, UseFormSetValue, useWatch } from "react-hook-form";
+import { faChevronDown, faChevronRight } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { createNotification } from "@app/components/notifications";
+import { Checkbox, Select, SelectItem, Td, Tr } from "@app/components/v2";
+import { OrgPermissionAppConnectionActions } from "@app/context/OrgPermissionContext/types";
+import { useToggle } from "@app/hooks";
+
+import { TFormSchema } from "../OrgRoleModifySection.utils";
+
+type Props = {
+  isEditable: boolean;
+  setValue: UseFormSetValue<TFormSchema>;
+  control: Control<TFormSchema>;
+};
+
+enum Permission {
+  NoAccess = "no-access",
+  ReadOnly = "read-only",
+  FullAccess = "full-access",
+  Custom = "custom"
+}
+
+const PERMISSION_ACTIONS = [
+  { action: OrgPermissionAppConnectionActions.Read, label: "Read" },
+  { action: OrgPermissionAppConnectionActions.Create, label: "Create" },
+  { action: OrgPermissionAppConnectionActions.Edit, label: "Modify" },
+  { action: OrgPermissionAppConnectionActions.Delete, label: "Remove" },
+  { action: OrgPermissionAppConnectionActions.Connect, label: "Connect" }
+] as const;
+
+export const OrgPermissionAppConnectionRow = ({ isEditable, control, setValue }: Props) => {
+  const [isRowExpanded, setIsRowExpanded] = useToggle();
+  const [isCustom, setIsCustom] = useToggle();
+
+  const rule = useWatch({
+    control,
+    name: "permissions.app-connections"
+  });
+
+  const selectedPermissionCategory = useMemo(() => {
+    const actions = Object.keys(rule || {}) as Array<keyof typeof rule>;
+    const totalActions = PERMISSION_ACTIONS.length;
+    const score = actions.map((key) => (rule?.[key] ? 1 : 0)).reduce((a, b) => a + b, 0 as number);
+
+    if (isCustom) return Permission.Custom;
+    if (score === 0) return Permission.NoAccess;
+    if (score === totalActions) return Permission.FullAccess;
+    if (score === 1 && rule?.[OrgPermissionAppConnectionActions.Read]) return Permission.ReadOnly;
+
+    return Permission.Custom;
+  }, [rule, isCustom]);
+
+  useEffect(() => {
+    if (selectedPermissionCategory === Permission.Custom) setIsCustom.on();
+    else setIsCustom.off();
+  }, [selectedPermissionCategory]);
+
+  useEffect(() => {
+    const isRowCustom = selectedPermissionCategory === Permission.Custom;
+    if (isRowCustom) {
+      setIsRowExpanded.on();
+    }
+  }, []);
+
+  const handlePermissionChange = (val: Permission) => {
+    if (!val) return;
+    if (val === Permission.Custom) {
+      setIsRowExpanded.on();
+      setIsCustom.on();
+      return;
+    }
+    setIsCustom.off();
+
+    switch (val) {
+      case Permission.FullAccess:
+        setValue(
+          "permissions.app-connections",
+          {
+            [OrgPermissionAppConnectionActions.Read]: true,
+            [OrgPermissionAppConnectionActions.Edit]: true,
+            [OrgPermissionAppConnectionActions.Create]: true,
+            [OrgPermissionAppConnectionActions.Delete]: true,
+            [OrgPermissionAppConnectionActions.Connect]: true
+          },
+          { shouldDirty: true }
+        );
+        break;
+      case Permission.ReadOnly:
+        setValue(
+          "permissions.app-connections",
+          {
+            [OrgPermissionAppConnectionActions.Read]: true,
+            [OrgPermissionAppConnectionActions.Edit]: false,
+            [OrgPermissionAppConnectionActions.Create]: false,
+            [OrgPermissionAppConnectionActions.Delete]: false,
+            [OrgPermissionAppConnectionActions.Connect]: false
+          },
+          { shouldDirty: true }
+        );
+        break;
+
+      case Permission.NoAccess:
+      default:
+        setValue(
+          "permissions.app-connections",
+          {
+            [OrgPermissionAppConnectionActions.Read]: false,
+            [OrgPermissionAppConnectionActions.Edit]: false,
+            [OrgPermissionAppConnectionActions.Create]: false,
+            [OrgPermissionAppConnectionActions.Delete]: false,
+            [OrgPermissionAppConnectionActions.Connect]: false
+          },
+          { shouldDirty: true }
+        );
+    }
+  };
+
+  return (
+    <>
+      <Tr
+        className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
+        onClick={() => setIsRowExpanded.toggle()}
+      >
+        <Td>
+          <FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
+        </Td>
+        <Td>App Connections</Td>
+        <Td>
+          <Select
+            value={selectedPermissionCategory}
+            className="w-40 bg-mineshaft-600"
+            dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
+            onValueChange={handlePermissionChange}
+            isDisabled={!isEditable}
+          >
+            <SelectItem value={Permission.NoAccess}>No Access</SelectItem>
+            <SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
+            <SelectItem value={Permission.FullAccess}>Full Access</SelectItem>
+            <SelectItem value={Permission.Custom}>Custom</SelectItem>
+          </Select>
+        </Td>
+      </Tr>
+      {isRowExpanded && (
+        <Tr>
+          <Td
+            colSpan={3}
+            className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
+          >
+            <div className="grid grid-cols-3 gap-4">
+              {PERMISSION_ACTIONS.map(({ action, label }) => {
+                return (
+                  <Controller
+                    name={`permissions.app-connections.${action}`}
+                    key={`permissions.app-connections.${action}`}
+                    control={control}
+                    render={({ field }) => (
+                      <Checkbox
+                        isChecked={field.value}
+                        onCheckedChange={(e) => {
+                          if (!isEditable) {
+                            createNotification({
+                              type: "error",
+                              text: "Failed to update default role"
+                            });
+                            return;
+                          }
+                          field.onChange(e);
+                        }}
+                        id={`permissions.app-connections.${action}`}
+                      >
+                        {label}
+                      </Checkbox>
+                    )}
+                  />
+                );
+              })}
+            </div>
+          </Td>
+        </Tr>
+      )}
+    </>
+  );
+};
diff --git a/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/RolePermissionsSection.tsx b/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/RolePermissionsSection.tsx
index 5d359423a6..44f80c18d9 100644
--- a/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/RolePermissionsSection.tsx
+++ b/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/RolePermissionsSection.tsx
@@ -5,6 +5,7 @@ import { createNotification } from "@app/components/notifications";
 import { Button, Table, TableContainer, TBody, Th, THead, Tr } from "@app/components/v2";
 import { OrgPermissionSubjects, useOrganization } from "@app/context";
 import { useGetOrgRole, useUpdateOrgRole } from "@app/hooks/api";
+import { OrgPermissionAppConnectionRow } from "@app/pages/organization/RoleByIDPage/components/RolePermissionsSection/OrgPermissionAppConnectionRow";
 
 import {
   formRolePermission2API,
@@ -69,8 +70,7 @@ const SIMPLE_PERMISSION_OPTIONS = [
     title: "External KMS",
     formName: OrgPermissionSubjects.Kms
   },
-  { title: "Project Templates", formName: OrgPermissionSubjects.ProjectTemplates },
-  { title: "App Connections", formName: OrgPermissionSubjects.AppConnections }
+  { title: "Project Templates", formName: OrgPermissionSubjects.ProjectTemplates }
 ] as const;
 
 type Props = {
@@ -165,6 +165,11 @@ export const RolePermissionsSection = ({ roleId }: Props) => {
                   />
                 );
               })}
+              <OrgPermissionAppConnectionRow
+                control={control}
+                setValue={setValue}
+                isEditable={isCustomRole}
+              />
               <OrgRoleWorkspaceRow
                 control={control}
                 setValue={setValue}
diff --git a/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/AppConnectionsTab.tsx b/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/AppConnectionsTab.tsx
index 6f775109c8..393bb4381f 100644
--- a/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/AppConnectionsTab.tsx
+++ b/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/AppConnectionsTab.tsx
@@ -1,14 +1,10 @@
-import {
-  faArrowUpRightFromSquare,
-  faBookOpen,
-  faPlus,
-  faWrench
-} from "@fortawesome/free-solid-svg-icons";
+import { faArrowUpRightFromSquare, faBookOpen, faPlus } from "@fortawesome/free-solid-svg-icons";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 
 import { OrgPermissionCan } from "@app/components/permissions";
 import { Button } from "@app/components/v2";
-import { OrgPermissionActions, OrgPermissionSubjects, useSubscription } from "@app/context";
+import { OrgPermissionSubjects } from "@app/context";
+import { OrgPermissionAppConnectionActions } from "@app/context/OrgPermissionContext/types";
 import { withPermission } from "@app/hoc";
 import { usePopUp } from "@app/hooks";
 
@@ -16,24 +12,8 @@ import { AddAppConnectionModal, AppConnectionsTable } from "./components";
 
 export const AppConnectionsTab = withPermission(
   () => {
-    const { subscription } = useSubscription();
-
     const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["addConnection"] as const);
 
-    // TODO: remove once live
-    if (!subscription?.appConnections)
-      return (
-        <div className="m-auto mt-40 flex w-full max-w-2xl flex-col items-center rounded-md bg-mineshaft-800 px-2 pt-4 text-bunker-300">
-          <FontAwesomeIcon icon={faWrench} size="2xl" />
-          <div className="flex flex-col items-center py-4">
-            <div className="text-lg text-mineshaft-200">
-              App Connections are currently unavailable.
-            </div>
-            <span className="text-mineshaft-300">Check back soon.</span>
-          </div>
-        </div>
-      );
-
     return (
       <div>
         <div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
@@ -62,7 +42,7 @@ export const AppConnectionsTab = withPermission(
               </p>
             </div>
             <OrgPermissionCan
-              I={OrgPermissionActions.Create}
+              I={OrgPermissionAppConnectionActions.Create}
               a={OrgPermissionSubjects.AppConnections}
             >
               {(isAllowed) => (
@@ -91,7 +71,7 @@ export const AppConnectionsTab = withPermission(
     );
   },
   {
-    action: OrgPermissionActions.Read,
+    action: OrgPermissionAppConnectionActions.Read,
     subject: OrgPermissionSubjects.AppConnections
   }
 );
diff --git a/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionForm/GitHubConnectionForm.tsx b/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionForm/GitHubConnectionForm.tsx
index aa7865cbb5..f9ff8d0e57 100644
--- a/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionForm/GitHubConnectionForm.tsx
+++ b/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionForm/GitHubConnectionForm.tsx
@@ -132,7 +132,7 @@ export const GitHubConnectionForm = ({ appConnection }: Props) => {
                 {Object.values(GitHubConnectionMethod).map((method) => {
                   return (
                     <SelectItem value={method} key={method}>
-                      {methodDetails.name}{" "}
+                      {getAppConnectionMethodDetails(method).name}{" "}
                       {method === GitHubConnectionMethod.App ? " (Recommended)" : ""}
                     </SelectItem>
                   );
diff --git a/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionRow.tsx b/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionRow.tsx
index ea53778ba1..a733bae8ed 100644
--- a/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionRow.tsx
+++ b/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionRow.tsx
@@ -23,7 +23,8 @@ import {
   Tooltip,
   Tr
 } from "@app/components/v2";
-import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
+import { OrgPermissionSubjects } from "@app/context";
+import { OrgPermissionAppConnectionActions } from "@app/context/OrgPermissionContext/types";
 import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
 import { useToggle } from "@app/hooks";
 import { TAppConnection } from "@app/hooks/api/appConnections";
@@ -119,7 +120,7 @@ export const AppConnectionRow = ({
                 Copy Connection ID
               </DropdownMenuItem>
               <OrgPermissionCan
-                I={OrgPermissionActions.Edit}
+                I={OrgPermissionAppConnectionActions.Edit}
                 a={OrgPermissionSubjects.AppConnections}
               >
                 {(isAllowed: boolean) => (
@@ -133,7 +134,7 @@ export const AppConnectionRow = ({
                 )}
               </OrgPermissionCan>
               <OrgPermissionCan
-                I={OrgPermissionActions.Edit}
+                I={OrgPermissionAppConnectionActions.Edit}
                 a={OrgPermissionSubjects.AppConnections}
               >
                 {(isAllowed: boolean) => (
@@ -147,7 +148,7 @@ export const AppConnectionRow = ({
                 )}
               </OrgPermissionCan>
               <OrgPermissionCan
-                I={OrgPermissionActions.Delete}
+                I={OrgPermissionAppConnectionActions.Delete}
                 a={OrgPermissionSubjects.AppConnections}
               >
                 {(isAllowed: boolean) => (
diff --git a/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionsTable.tsx b/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionsTable.tsx
index ed9a35d39b..db5e218ec0 100644
--- a/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionsTable.tsx
+++ b/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/AppConnectionsTable.tsx
@@ -29,7 +29,6 @@ import {
   THead,
   Tr
 } from "@app/components/v2";
-import { useSubscription } from "@app/context";
 import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
 import { usePagination, usePopUp, useResetPageHelper } from "@app/hooks";
 import { TAppConnection, useListAppConnections } from "@app/hooks/api/appConnections";
@@ -52,11 +51,7 @@ type AppConnectionFilters = {
 };
 
 export const AppConnectionsTable = () => {
-  const { subscription } = useSubscription();
-
-  const { isLoading, data: appConnections = [] } = useListAppConnections({
-    enabled: subscription?.appConnections
-  });
+  const { isLoading, data: appConnections = [] } = useListAppConnections();
 
   const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
     "deleteConnection",
diff --git a/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/DeleteAppConnectionModal.tsx b/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/DeleteAppConnectionModal.tsx
index fc42f6a4ca..a2f751405e 100644
--- a/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/DeleteAppConnectionModal.tsx
+++ b/frontend/src/pages/organization/SettingsPage/components/AppConnectionsTab/components/DeleteAppConnectionModal.tsx
@@ -33,7 +33,7 @@ export const DeleteAppConnectionModal = ({ isOpen, onOpenChange, appConnection }
       console.error(err);
 
       createNotification({
-        text: `Failed remove ${APP_CONNECTION_MAP[app].name} connection`,
+        text: `Failed to remove ${APP_CONNECTION_MAP[app].name} connection`,
         type: "error"
       });
     }
diff --git a/frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx b/frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx
index 3a109ceb07..3a9e311fdf 100644
--- a/frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx
+++ b/frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx
@@ -8,6 +8,7 @@ import {
 import {
   PermissionConditionOperators,
   ProjectPermissionDynamicSecretActions,
+  ProjectPermissionSecretSyncActions,
   TPermissionCondition,
   TPermissionConditionOperators
 } from "@app/context/ProjectPermissionContext/types";
@@ -37,6 +38,16 @@ const DynamicSecretPolicyActionSchema = z.object({
   [ProjectPermissionDynamicSecretActions.Lease]: z.boolean().optional()
 });
 
+const SecretSyncPolicyActionSchema = z.object({
+  [ProjectPermissionSecretSyncActions.Read]: z.boolean().optional(),
+  [ProjectPermissionSecretSyncActions.Create]: z.boolean().optional(),
+  [ProjectPermissionSecretSyncActions.Edit]: z.boolean().optional(),
+  [ProjectPermissionSecretSyncActions.Delete]: z.boolean().optional(),
+  [ProjectPermissionSecretSyncActions.SyncSecrets]: z.boolean().optional(),
+  [ProjectPermissionSecretSyncActions.ImportSecrets]: z.boolean().optional(),
+  [ProjectPermissionSecretSyncActions.RemoveSecrets]: z.boolean().optional()
+});
+
 const SecretRollbackPolicyActionSchema = z.object({
   read: z.boolean().optional(),
   create: z.boolean().optional()
@@ -137,7 +148,8 @@ export const projectRoleFormSchema = z.object({
       [ProjectPermissionSub.Tags]: GeneralPolicyActionSchema.array().default([]),
       [ProjectPermissionSub.SecretRotation]: GeneralPolicyActionSchema.array().default([]),
       [ProjectPermissionSub.Kms]: GeneralPolicyActionSchema.array().default([]),
-      [ProjectPermissionSub.Cmek]: CmekPolicyActionSchema.array().default([])
+      [ProjectPermissionSub.Cmek]: CmekPolicyActionSchema.array().default([]),
+      [ProjectPermissionSub.SecretSyncs]: SecretSyncPolicyActionSchema.array().default([])
     })
     .partial()
     .optional()
@@ -331,6 +343,31 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
       if (canDelete) formVal[subject]![0].delete = true;
       if (canEncrypt) formVal[subject]![0].encrypt = true;
       if (canDecrypt) formVal[subject]![0].decrypt = true;
+      return;
+    }
+
+    if (subject === ProjectPermissionSub.SecretSyncs) {
+      const canRead = action.includes(ProjectPermissionSecretSyncActions.Read);
+      const canEdit = action.includes(ProjectPermissionSecretSyncActions.Edit);
+      const canDelete = action.includes(ProjectPermissionSecretSyncActions.Delete);
+      const canCreate = action.includes(ProjectPermissionSecretSyncActions.Create);
+      const canSyncSecrets = action.includes(ProjectPermissionSecretSyncActions.SyncSecrets);
+      const canImportSecrets = action.includes(ProjectPermissionSecretSyncActions.ImportSecrets);
+      const canRemoveSecrets = action.includes(ProjectPermissionSecretSyncActions.RemoveSecrets);
+
+      if (!formVal[subject]) formVal[subject] = [{}];
+
+      // from above statement we are sure it won't be undefined
+      if (canRead) formVal[subject]![0][ProjectPermissionSecretSyncActions.Read] = true;
+      if (canEdit) formVal[subject]![0][ProjectPermissionSecretSyncActions.Edit] = true;
+      if (canCreate) formVal[subject]![0][ProjectPermissionSecretSyncActions.Create] = true;
+      if (canDelete) formVal[subject]![0][ProjectPermissionSecretSyncActions.Delete] = true;
+      if (canSyncSecrets)
+        formVal[subject]![0][ProjectPermissionSecretSyncActions.SyncSecrets] = true;
+      if (canImportSecrets)
+        formVal[subject]![0][ProjectPermissionSecretSyncActions.ImportSecrets] = true;
+      if (canRemoveSecrets)
+        formVal[subject]![0][ProjectPermissionSecretSyncActions.RemoveSecrets] = true;
     }
   });
   return formVal;
@@ -670,5 +707,23 @@ export const PROJECT_PERMISSION_OBJECT: TProjectPermissionObject = {
       { label: "Perform rollback", value: "create" },
       { label: "View", value: "read" }
     ]
+  },
+  [ProjectPermissionSub.SecretSyncs]: {
+    title: "Secret Syncs",
+    actions: [
+      { label: "Read", value: ProjectPermissionSecretSyncActions.Read },
+      { label: "Create", value: ProjectPermissionSecretSyncActions.Create },
+      { label: "Modify", value: ProjectPermissionSecretSyncActions.Edit },
+      { label: "Remove", value: ProjectPermissionSecretSyncActions.Delete },
+      { label: "Trigger Syncs", value: ProjectPermissionSecretSyncActions.SyncSecrets },
+      {
+        label: "Import Secrets from Destination",
+        value: ProjectPermissionSecretSyncActions.ImportSecrets
+      },
+      {
+        label: "Remove Secrets from Destination",
+        value: ProjectPermissionSecretSyncActions.RemoveSecrets
+      }
+    ]
   }
 };
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx
index 6ee64296eb..aec636da7f 100644
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx
@@ -1,220 +1,41 @@
-import { useCallback, useEffect, useState } from "react";
 import { Helmet } from "react-helmet";
 import { useTranslation } from "react-i18next";
-import { useNavigate } from "@tanstack/react-router";
-import { motion } from "framer-motion";
+import { faInfoCircle } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { useNavigate, useSearch } from "@tanstack/react-router";
 
-import { createNotification } from "@app/components/notifications";
 import { ProjectPermissionCan } from "@app/components/permissions";
-import { ContentLoader } from "@app/components/v2";
+import { Badge, Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
+import { ROUTE_PATHS } from "@app/const/routes";
 import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
-import {
-  useDeleteIntegration,
-  useDeleteIntegrationAuths,
-  useGetCloudIntegrations,
-  useGetWorkspaceAuthorizations,
-  useGetWorkspaceIntegrations
-} from "@app/hooks/api";
-import { IntegrationAuth } from "@app/hooks/api/types";
-
-import { CloudIntegrationSection } from "./components/CloudIntegrationSection";
-import { FrameworkIntegrationSection } from "./components/FrameworkIntegrationSection";
-import { InfrastructureIntegrationSection } from "./components/InfrastructureIntegrationSection/InfrastructureIntegrationSection";
-import { IntegrationsSection } from "./components/IntegrationsSection";
-import { redirectForProviderAuth } from "./IntegrationsListPage.utils";
+import { IntegrationsListPageTabs } from "@app/types/integrations";
 
-enum IntegrationView {
-  List = "list",
-  New = "new"
-}
+import {
+  FrameworkIntegrationTab,
+  InfrastructureIntegrationTab,
+  NativeIntegrationsTab,
+  SecretSyncsTab
+} from "./components";
 
-const Page = () => {
-  const { currentWorkspace } = useWorkspace();
+export const IntegrationsListPage = () => {
   const navigate = useNavigate();
-  const { environments, id: workspaceId } = currentWorkspace;
-  const [view, setView] = useState<IntegrationView>(IntegrationView.New);
-
-  const { data: cloudIntegrations, isPending: isCloudIntegrationsLoading } =
-    useGetCloudIntegrations();
-
-  const {
-    data: integrationAuths,
-    isPending: isIntegrationAuthLoading,
-    isFetching: isIntegrationAuthFetching
-  } = useGetWorkspaceAuthorizations(
-    workspaceId,
-    useCallback((data: IntegrationAuth[]) => {
-      const groupBy: Record<string, IntegrationAuth> = {};
-      data.forEach((el) => {
-        groupBy[el.integration] = el;
-      });
-      return groupBy;
-    }, [])
-  );
-
-  // mutation
-  const {
-    data: integrations,
-    isPending: isIntegrationLoading,
-    isFetching: isIntegrationFetching,
-    isFetched: isIntegrationsFetched
-  } = useGetWorkspaceIntegrations(workspaceId);
-
-  const { mutateAsync: deleteIntegration } = useDeleteIntegration();
-  const {
-    mutateAsync: deleteIntegrationAuths,
-    isSuccess: isDeleteIntegrationAuthSuccess,
-    reset: resetDeleteIntegrationAuths
-  } = useDeleteIntegrationAuths();
-
-  const isIntegrationsAuthorizedEmpty = !Object.keys(integrationAuths || {}).length;
-  const isIntegrationsEmpty = !integrations?.length;
-  // summary: this use effect is trigger when all integration auths are removed thus deactivate bot
-  // details: so on successfully deleting an integration auth, immediately integration list is refeteched
-  // After the refetch is completed check if its empty. Then set bot active and reset the submit hook for isSuccess to go back to false
-  useEffect(() => {
-    if (
-      isDeleteIntegrationAuthSuccess &&
-      !isIntegrationFetching &&
-      !isIntegrationAuthFetching &&
-      isIntegrationsAuthorizedEmpty &&
-      isIntegrationsEmpty
-    ) {
-      resetDeleteIntegrationAuths();
-    }
-  }, [
-    isIntegrationFetching,
-    isDeleteIntegrationAuthSuccess,
-    isIntegrationAuthFetching,
-    isIntegrationsAuthorizedEmpty,
-    isIntegrationsEmpty
-  ]);
-
-  useEffect(() => {
-    setView(integrations?.length ? IntegrationView.List : IntegrationView.New);
-  }, [isIntegrationsFetched]);
-
-  const handleProviderIntegration = async (provider: string) => {
-    const selectedCloudIntegration = cloudIntegrations?.find(({ slug }) => provider === slug);
-    if (!selectedCloudIntegration) return;
-
-    try {
-      redirectForProviderAuth(currentWorkspace.id, navigate, selectedCloudIntegration);
-    } catch (error) {
-      console.error(error);
-    }
-  };
-
-  // function to strat integration for a provider
-  // confirmation to user passing the bot key for provider to get secret access
-  const handleProviderIntegrationStart = (provider: string) => {
-    handleProviderIntegration(provider);
-  };
-
-  const handleIntegrationDelete = async (
-    integrationId: string,
-    shouldDeleteIntegrationSecrets: boolean,
-    cb: () => void
-  ) => {
-    try {
-      await deleteIntegration({ id: integrationId, workspaceId, shouldDeleteIntegrationSecrets });
-      if (cb) cb();
-      createNotification({
-        type: "success",
-        text: "Deleted integration"
-      });
-    } catch (err) {
-      console.log(err);
-      createNotification({
-        type: "error",
-        text: "Failed to delete integration"
-      });
-    }
-  };
-
-  const handleIntegrationAuthRevoke = async (provider: string, cb?: () => void) => {
-    const integrationAuthForProvider = integrationAuths?.[provider];
-    if (!integrationAuthForProvider) return;
+  const { currentWorkspace } = useWorkspace();
+  const { t } = useTranslation();
 
-    try {
-      await deleteIntegrationAuths({
-        integration: provider,
-        workspaceId
-      });
-      if (cb) cb();
-      createNotification({
-        type: "success",
-        text: "Revoked provider authentication"
-      });
-    } catch (err) {
-      console.error(err);
-      createNotification({
-        type: "error",
-        text: "Failed to revoke provider authentication"
-      });
-    }
+  const { selectedTab } = useSearch({
+    from: ROUTE_PATHS.SecretManager.IntegrationsListPage.id
+  });
+
+  const updateSelectedTab = (tab: string) => {
+    navigate({
+      to: ROUTE_PATHS.SecretManager.IntegrationsListPage.path,
+      search: (prev) => ({ ...prev, selectedTab: tab }),
+      params: {
+        projectId: currentWorkspace.id
+      }
+    });
   };
 
-  if (isIntegrationLoading || isCloudIntegrationsLoading)
-    return (
-      <div className="flex flex-col items-center gap-2">
-        <ContentLoader text={["Loading integrations..."]} />
-      </div>
-    );
-
-  return (
-    <div className="container relative mx-auto max-w-7xl text-white">
-      <div className="relative">
-        {view === IntegrationView.List ? (
-          <motion.div
-            key="view-integrations"
-            transition={{ duration: 0.3 }}
-            initial={{ opacity: 0, translateX: 30 }}
-            animate={{ opacity: 1, translateX: 0 }}
-            exit={{ opacity: 0, translateX: 30 }}
-            className="w-full"
-          >
-            <IntegrationsSection
-              cloudIntegrations={cloudIntegrations}
-              onAddIntegration={() => setView(IntegrationView.New)}
-              isLoading={isIntegrationLoading}
-              integrations={integrations}
-              environments={environments}
-              onIntegrationDelete={handleIntegrationDelete}
-              workspaceId={workspaceId}
-            />
-          </motion.div>
-        ) : (
-          <motion.div
-            key="add-integration"
-            transition={{ duration: 0.3 }}
-            initial={{ opacity: 0, translateX: 30 }}
-            animate={{ opacity: 1, translateX: 0 }}
-            exit={{ opacity: 0, translateX: 30 }}
-            className="w-full"
-          >
-            <CloudIntegrationSection
-              onViewActiveIntegrations={
-                integrations?.length ? () => setView(IntegrationView.List) : undefined
-              }
-              isLoading={isCloudIntegrationsLoading || isIntegrationAuthLoading}
-              cloudIntegrations={cloudIntegrations}
-              integrationAuths={integrationAuths}
-              onIntegrationStart={handleProviderIntegrationStart}
-              onIntegrationRevoke={handleIntegrationAuthRevoke}
-            />
-            <FrameworkIntegrationSection />
-            <InfrastructureIntegrationSection />
-          </motion.div>
-        )}
-      </div>
-    </div>
-  );
-};
-
-export const IntegrationsListPage = () => {
-  const { t } = useTranslation();
-
   return (
     <>
       <Helmet>
@@ -223,14 +44,90 @@ export const IntegrationsListPage = () => {
         <meta property="og:title" content="Manage your .env files in seconds" />
         <meta name="og:description" content={t("integrations.description") as string} />
       </Helmet>
-      <ProjectPermissionCan
-        renderGuardBanner
-        passThrough={false}
-        I={ProjectPermissionActions.Read}
-        a={ProjectPermissionSub.Integrations}
-      >
-        <Page />
-      </ProjectPermissionCan>
+      <div className="container relative mx-auto max-w-7xl pb-12 text-white">
+        <div className="mx-6 mb-8">
+          <div className="mb-4 mt-6 flex flex-col items-start justify-between px-2 text-xl">
+            <h1 className="text-3xl font-semibold">Integrations</h1>
+            <p className="text-base text-bunker-300">
+              Manage integrations with third-party services.
+            </p>
+          </div>
+          <div className="mx-2 mb-4 flex flex-col rounded-r border-l-2 border-l-primary bg-mineshaft-300/5 px-4 py-2.5">
+            <div className="mb-1 flex items-center text-sm">
+              <FontAwesomeIcon icon={faInfoCircle} size="sm" className="mr-1 text-primary" />
+              Integrations Update
+            </div>
+            <p className="mb-2 mt-1 text-sm text-bunker-300">
+              Infisical is excited to announce{" "}
+              <a
+                className="text-bunker-200 underline decoration-primary-700 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
+                href="https://infisical.com/docs/integrations/secret-syncs/overview"
+                target="_blank"
+                rel="noopener noreferrer"
+              >
+                Secret Syncs
+              </a>
+              , a new way to sync your secrets to third-party services using{" "}
+              <a
+                className="text-bunker-200 underline decoration-primary-700 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
+                href="https://infisical.com/docs/integrations/app-connections/overview"
+                target="_blank"
+                rel="noopener noreferrer"
+              >
+                App Connections
+              </a>
+              , offering deeper customization and re-configurability.
+            </p>
+            <p className="text-sm text-bunker-300">
+              Existing integrations (now called Native Integrations) will continue to be supported
+              as we build out our Secret Sync library.
+            </p>
+          </div>
+          <Tabs value={selectedTab} onValueChange={updateSelectedTab}>
+            <TabList>
+              <Tab value={IntegrationsListPageTabs.SecretSyncs}>
+                Secret Syncs
+                <Badge variant="primary" className="ml-1 cursor-pointer text-xs">
+                  New
+                </Badge>
+              </Tab>
+              <Tab value={IntegrationsListPageTabs.NativeIntegrations}>Native Integrations</Tab>
+              <Tab value={IntegrationsListPageTabs.FrameworkIntegrations}>
+                Framework Integrations
+              </Tab>
+              <Tab value={IntegrationsListPageTabs.InfrastructureIntegrations}>
+                Infrastructure Integrations
+              </Tab>
+            </TabList>
+            <TabPanel value={IntegrationsListPageTabs.SecretSyncs}>
+              <ProjectPermissionCan
+                renderGuardBanner
+                passThrough={false}
+                I={ProjectPermissionActions.Read}
+                a={ProjectPermissionSub.SecretSyncs}
+              >
+                <SecretSyncsTab />
+              </ProjectPermissionCan>
+            </TabPanel>
+            <TabPanel value={IntegrationsListPageTabs.NativeIntegrations}>
+              <ProjectPermissionCan
+                renderGuardBanner
+                passThrough={false}
+                I={ProjectPermissionActions.Read}
+                a={ProjectPermissionSub.Integrations}
+              >
+                <NativeIntegrationsTab />
+              </ProjectPermissionCan>
+            </TabPanel>
+            <TabPanel value={IntegrationsListPageTabs.FrameworkIntegrations}>
+              <FrameworkIntegrationTab />
+            </TabPanel>
+            <TabPanel value={IntegrationsListPageTabs.InfrastructureIntegrations}>
+              <InfrastructureIntegrationTab />
+            </TabPanel>
+          </Tabs>
+        </div>
+      </div>
     </>
   );
 };
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx
index 5adb956646..6de44d95cf 100644
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx
@@ -75,12 +75,12 @@ export const CloudIntegrationSection = ({
 
   return (
     <div>
-      <div className="px-5">
-        {currentWorkspace?.environments.length === 0 && (
+      {currentWorkspace?.environments.length === 0 && (
+        <div className="px-5">
           <NoEnvironmentsBanner projectId={currentWorkspace.id} />
-        )}
-      </div>
-      <div className="flex flex-col items-start justify-between py-4 text-xl">
+        </div>
+      )}
+      <div className="m-4 mt-0 flex flex-col items-start justify-between px-2 text-xl">
         {onViewActiveIntegrations && (
           <Button
             variant="link"
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationSection/index.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationSection/index.tsx
deleted file mode 100644
index 1738b8179a..0000000000
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationSection/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export { FrameworkIntegrationSection } from "./FrameworkIntegrationSection";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationSection/FrameworkIntegrationSection.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationTab/FrameworkIntegrationTab.tsx
similarity index 95%
rename from frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationSection/FrameworkIntegrationSection.tsx
rename to frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationTab/FrameworkIntegrationTab.tsx
index 211759dccd..8c28af2410 100644
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationSection/FrameworkIntegrationSection.tsx
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationTab/FrameworkIntegrationTab.tsx
@@ -5,14 +5,14 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 
 import frameworks from "../json/frameworkIntegrations.json";
 
-export const FrameworkIntegrationSection = () => {
+export const FrameworkIntegrationTab = () => {
   const { t } = useTranslation();
 
   const sortedFrameworks = frameworks.sort((a, b) => a.name.localeCompare(b.name));
 
   return (
     <>
-      <div className="mb-4 mt-12 flex flex-col items-start justify-between px-2 text-xl">
+      <div className="mx-4 mb-4 flex flex-col items-start justify-between px-2 text-xl">
         <h1 className="text-3xl font-semibold">{t("integrations.framework-integrations")}</h1>
         <p className="text-base text-gray-400">{t("integrations.click-to-setup")}</p>
       </div>
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationTab/index.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationTab/index.tsx
new file mode 100644
index 0000000000..de5ab6c223
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/FrameworkIntegrationTab/index.tsx
@@ -0,0 +1 @@
+export { FrameworkIntegrationTab } from "./FrameworkIntegrationTab";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationSection/index.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationSection/index.tsx
deleted file mode 100644
index 8ca5a43c79..0000000000
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationSection/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export { InfrastructureIntegrationSection } from "./InfrastructureIntegrationSection";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationSection/InfrastructureIntegrationSection.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationTab/InfrastructureIntegrationTab.tsx
similarity index 88%
rename from frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationSection/InfrastructureIntegrationSection.tsx
rename to frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationTab/InfrastructureIntegrationTab.tsx
index 16a576359d..2fe16c3775 100644
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationSection/InfrastructureIntegrationSection.tsx
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationTab/InfrastructureIntegrationTab.tsx
@@ -1,17 +1,17 @@
 import integrations from "../json/infrastructureIntegrations.json";
 
-export const InfrastructureIntegrationSection = () => {
+export const InfrastructureIntegrationTab = () => {
   const sortedIntegrations = integrations.sort((a, b) => a.name.localeCompare(b.name));
 
   return (
     <>
-      <div className="mb-4 mt-12 flex flex-col items-start justify-between px-2 text-xl">
+      <div className="mx-4 mb-4 flex flex-col items-start justify-between px-2 text-xl">
         <h1 className="text-3xl font-semibold">Infrastructure Integrations</h1>
         <p className="text-base text-gray-400">
           Click on of the integration to read the documentation.
         </p>
       </div>
-      <div className="mx-2 grid grid-cols-2 gap-4 lg:grid-cols-3 2xl:grid-cols-4">
+      <div className="mx-6 grid grid-cols-2 gap-4 lg:grid-cols-3 2xl:grid-cols-4">
         {sortedIntegrations.map((integration) => (
           <a
             key={`framework-integration-${integration.slug}`}
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationTab/index.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationTab/index.tsx
new file mode 100644
index 0000000000..1cf3febd5e
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/InfrastructureIntegrationTab/index.tsx
@@ -0,0 +1 @@
+export { InfrastructureIntegrationTab } from "./InfrastructureIntegrationTab";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/IntegrationsSection.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/IntegrationsSection.tsx
deleted file mode 100644
index cf2e0067f0..0000000000
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/IntegrationsSection.tsx
+++ /dev/null
@@ -1,136 +0,0 @@
-import { faPlus } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-
-import { Button, Checkbox, DeleteActionModal, PageHeader } from "@app/components/v2";
-import { usePopUp, useToggle } from "@app/hooks";
-import { TCloudIntegration, TIntegration } from "@app/hooks/api/types";
-
-import { IntegrationsTable } from "./components";
-
-type Props = {
-  environments: Array<{ name: string; slug: string; id: string }>;
-  integrations?: TIntegration[];
-  cloudIntegrations?: TCloudIntegration[];
-  isLoading?: boolean;
-  onIntegrationDelete: (
-    integrationId: string,
-    shouldDeleteIntegrationSecrets: boolean,
-    cb: () => void
-  ) => Promise<void>;
-  workspaceId: string;
-  onAddIntegration: () => void;
-};
-
-export const IntegrationsSection = ({
-  integrations = [],
-  environments = [],
-  isLoading,
-  onIntegrationDelete,
-  workspaceId,
-  onAddIntegration,
-  cloudIntegrations = []
-}: Props) => {
-  const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
-    "deleteConfirmation",
-    "deleteSecretsConfirmation"
-  ] as const);
-
-  const [shouldDeleteSecrets, setShouldDeleteSecrets] = useToggle(false);
-
-  return (
-    <div className="mb-8">
-      <PageHeader
-        title="Integrations"
-        description="Manage integrations with third-party services."
-      />
-      <div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
-        <div className="mb-4 flex items-center justify-between">
-          <p className="text-xl font-semibold text-mineshaft-100">Active Integrations</p>
-          <Button
-            colorSchema="primary"
-            type="submit"
-            leftIcon={<FontAwesomeIcon icon={faPlus} />}
-            onClick={onAddIntegration}
-          >
-            Add Integration
-          </Button>
-        </div>
-        <IntegrationsTable
-          cloudIntegrations={cloudIntegrations}
-          integrations={integrations}
-          isLoading={isLoading}
-          workspaceId={workspaceId}
-          environments={environments}
-          onDeleteIntegration={(integration) => {
-            setShouldDeleteSecrets.off();
-            handlePopUpOpen("deleteConfirmation", integration);
-          }}
-        />
-      </div>
-      <DeleteActionModal
-        isOpen={popUp.deleteConfirmation.isOpen}
-        title={`Are you sure want to remove ${
-          (popUp?.deleteConfirmation.data as TIntegration)?.integration || " "
-        } integration for ${
-          (popUp?.deleteConfirmation.data as TIntegration)?.app || "this project"
-        }?`}
-        onChange={(isOpen) => handlePopUpToggle("deleteConfirmation", isOpen)}
-        deleteKey={
-          ((popUp?.deleteConfirmation?.data as TIntegration)?.integration ===
-            "azure-app-configuration" &&
-            (popUp?.deleteConfirmation?.data as TIntegration)?.app
-              ?.split("//")[1]
-              ?.split(".")[0]) ||
-          (popUp?.deleteConfirmation?.data as TIntegration)?.app ||
-          (popUp?.deleteConfirmation?.data as TIntegration)?.owner ||
-          (popUp?.deleteConfirmation?.data as TIntegration)?.path ||
-          (popUp?.deleteConfirmation?.data as TIntegration)?.integration ||
-          ""
-        }
-        onDeleteApproved={async () => {
-          if (shouldDeleteSecrets) {
-            handlePopUpOpen("deleteSecretsConfirmation");
-            return;
-          }
-
-          await onIntegrationDelete(
-            (popUp?.deleteConfirmation.data as TIntegration).id,
-            false,
-            () => handlePopUpClose("deleteConfirmation")
-          );
-        }}
-      >
-        {(popUp?.deleteConfirmation?.data as TIntegration)?.integration === "github" && (
-          <div className="mt-4">
-            <Checkbox
-              id="delete-integration-secrets"
-              checkIndicatorBg="text-white"
-              onCheckedChange={() => setShouldDeleteSecrets.toggle()}
-            >
-              Delete previously synced secrets from the destination
-            </Checkbox>
-          </div>
-        )}
-      </DeleteActionModal>
-      <DeleteActionModal
-        isOpen={popUp.deleteSecretsConfirmation.isOpen}
-        title={`Are you sure you also want to delete secrets on ${
-          (popUp?.deleteConfirmation.data as TIntegration)?.integration
-        }?`}
-        subTitle="By confirming, you acknowledge that all secrets managed by this integration will be removed from the destination. This action is irreversible."
-        onChange={(isOpen) => handlePopUpToggle("deleteSecretsConfirmation", isOpen)}
-        deleteKey="confirm"
-        onDeleteApproved={async () => {
-          await onIntegrationDelete(
-            (popUp?.deleteConfirmation.data as TIntegration).id,
-            true,
-            () => {
-              handlePopUpClose("deleteSecretsConfirmation");
-              handlePopUpClose("deleteConfirmation");
-            }
-          );
-        }}
-      />
-    </div>
-  );
-};
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/components/index.ts b/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/components/index.ts
deleted file mode 100644
index d9567592c0..0000000000
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/components/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./IntegrationsTable";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/index.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/index.tsx
deleted file mode 100644
index 6f40d79fa8..0000000000
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export { IntegrationsSection } from "./IntegrationsSection";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/components/IntegrationDetails.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/IntegrationDetails.tsx
similarity index 100%
rename from frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/components/IntegrationDetails.tsx
rename to frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/IntegrationDetails.tsx
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/components/IntegrationRow.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/IntegrationRow.tsx
similarity index 100%
rename from frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/components/IntegrationRow.tsx
rename to frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/IntegrationRow.tsx
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/components/IntegrationsTable.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/IntegrationsTable.tsx
similarity index 93%
rename from frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/components/IntegrationsTable.tsx
rename to frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/IntegrationsTable.tsx
index ea2ecd8887..a8d2cccd5d 100644
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/IntegrationsSection/components/IntegrationsTable.tsx
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/IntegrationsTable.tsx
@@ -7,7 +7,7 @@ import {
   faClock,
   faFilter,
   faMagnifyingGlass,
-  faPlug,
+  faRotate,
   faSearch,
   faWarning
 } from "@fortawesome/free-solid-svg-icons";
@@ -85,16 +85,11 @@ export const IntegrationsTable = ({
 }: Props) => {
   const { mutate: syncIntegration } = useSyncIntegration();
 
-  const initialFilters = useMemo(
-    () => ({
-      environmentIds: environments.map((env) => env.id),
-      integrations: [...new Set(integrations.map(({ integration }) => integration))],
-      status: Object.values(IntegrationStatus)
-    }),
-    [environments, integrations]
-  );
-
-  const [filters, setFilters] = useState<IntegrationFilters>(initialFilters);
+  const [filters, setFilters] = useState<IntegrationFilters>({
+    status: [],
+    integrations: [],
+    environmentIds: []
+  });
 
   const cloudIntegrationMap = useMemo(() => {
     return new Map(
@@ -130,18 +125,33 @@ export const IntegrationsTable = ({
         .filter((integration) => {
           const { secretPath, envId, isSynced } = integration;
 
-          if (!filters.status.includes(IntegrationStatus.Synced) && isSynced) return false;
-          if (!filters.status.includes(IntegrationStatus.NotSynced) && isSynced === false)
+          if (
+            filters.status.length &&
+            !filters.status.includes(IntegrationStatus.Synced) &&
+            isSynced
+          )
+            return false;
+          if (
+            filters.status.length &&
+            !filters.status.includes(IntegrationStatus.NotSynced) &&
+            isSynced === false
+          )
             return false;
           if (
+            filters.status.length &&
             !filters.status.includes(IntegrationStatus.PendingSync) &&
             typeof isSynced !== "boolean"
           )
             return false;
 
-          if (!filters.integrations.includes(integration.integration)) return false;
+          if (
+            filters.integrations.length &&
+            !filters.integrations.includes(integration.integration)
+          )
+            return false;
 
-          if (!filters.environmentIds.includes(envId)) return false;
+          if (filters.environmentIds.length && !filters.environmentIds.includes(envId))
+            return false;
 
           return (
             integration.integration
@@ -216,9 +226,7 @@ export const IntegrationsTable = ({
     orderDirection === OrderByDirection.DESC && orderBy === col ? faArrowUp : faArrowDown;
 
   const isTableFiltered =
-    filters.integrations.length !== initialFilters.integrations.length ||
-    filters.environmentIds.length !== initialFilters.environmentIds.length ||
-    filters.status.length !== initialFilters.status.length;
+    filters.integrations.length || filters.environmentIds.length || filters.status.length;
 
   return (
     <div>
@@ -439,7 +447,7 @@ export const IntegrationsTable = ({
                 ? "No integrations match search..."
                 : "This project has no integrations configured"
             }
-            icon={integrations.length ? faSearch : faPlug}
+            icon={integrations.length ? faSearch : faRotate}
           />
         )}
       </TableContainer>
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/NativeIntegrationsTab.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/NativeIntegrationsTab.tsx
new file mode 100644
index 0000000000..1479ac4bde
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/NativeIntegrationsTab.tsx
@@ -0,0 +1,269 @@
+import { useCallback, useEffect, useState } from "react";
+import { faPlus } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { useNavigate } from "@tanstack/react-router";
+
+import { createNotification } from "@app/components/notifications";
+import { Button, Checkbox, DeleteActionModal, Spinner } from "@app/components/v2";
+import { useWorkspace } from "@app/context";
+import { usePopUp, useToggle } from "@app/hooks";
+import {
+  useDeleteIntegration,
+  useDeleteIntegrationAuths,
+  useGetCloudIntegrations,
+  useGetWorkspaceAuthorizations,
+  useGetWorkspaceIntegrations
+} from "@app/hooks/api";
+import { IntegrationAuth } from "@app/hooks/api/integrationAuth/types";
+import { TIntegration } from "@app/hooks/api/integrations/types";
+
+import { redirectForProviderAuth } from "../../IntegrationsListPage.utils";
+import { CloudIntegrationSection } from "../CloudIntegrationSection";
+import { IntegrationsTable } from "./IntegrationsTable";
+
+enum IntegrationView {
+  List = "list",
+  New = "new"
+}
+
+export const NativeIntegrationsTab = () => {
+  const { currentWorkspace } = useWorkspace();
+  const { environments, id: workspaceId } = currentWorkspace;
+  const navigate = useNavigate();
+
+  const { data: cloudIntegrations, isPending: isCloudIntegrationsLoading } =
+    useGetCloudIntegrations();
+
+  const {
+    data: integrationAuths,
+    isPending: isIntegrationAuthLoading,
+    isFetching: isIntegrationAuthFetching
+  } = useGetWorkspaceAuthorizations(
+    workspaceId,
+    useCallback((data: IntegrationAuth[]) => {
+      const groupBy: Record<string, IntegrationAuth> = {};
+      data.forEach((el) => {
+        groupBy[el.integration] = el;
+      });
+      return groupBy;
+    }, [])
+  );
+
+  // mutation
+  const {
+    data: integrations,
+    isPending: isIntegrationLoading,
+    isFetching: isIntegrationFetching
+  } = useGetWorkspaceIntegrations(workspaceId);
+
+  const { mutateAsync: deleteIntegration } = useDeleteIntegration();
+  const {
+    mutateAsync: deleteIntegrationAuths,
+    isSuccess: isDeleteIntegrationAuthSuccess,
+    reset: resetDeleteIntegrationAuths
+  } = useDeleteIntegrationAuths();
+
+  const isIntegrationsAuthorizedEmpty = !Object.keys(integrationAuths || {}).length;
+  const isIntegrationsEmpty = !integrations?.length;
+  // summary: this use effect is trigger when all integration auths are removed thus deactivate bot
+  // details: so on successfully deleting an integration auth, immediately integration list is refeteched
+  // After the refetch is completed check if its empty. Then set bot active and reset the submit hook for isSuccess to go back to false
+  useEffect(() => {
+    if (
+      isDeleteIntegrationAuthSuccess &&
+      !isIntegrationFetching &&
+      !isIntegrationAuthFetching &&
+      isIntegrationsAuthorizedEmpty &&
+      isIntegrationsEmpty
+    ) {
+      resetDeleteIntegrationAuths();
+    }
+  }, [
+    isIntegrationFetching,
+    isDeleteIntegrationAuthSuccess,
+    isIntegrationAuthFetching,
+    isIntegrationsAuthorizedEmpty,
+    isIntegrationsEmpty
+  ]);
+
+  const handleProviderIntegration = async (provider: string) => {
+    const selectedCloudIntegration = cloudIntegrations?.find(({ slug }) => provider === slug);
+    if (!selectedCloudIntegration) return;
+
+    try {
+      redirectForProviderAuth(currentWorkspace.id, navigate, selectedCloudIntegration);
+    } catch (error) {
+      console.error(error);
+    }
+  };
+
+  // function to strat integration for a provider
+  // confirmation to user passing the bot key for provider to get secret access
+  const handleProviderIntegrationStart = (provider: string) => {
+    handleProviderIntegration(provider);
+  };
+
+  const handleIntegrationDelete = async (
+    integrationId: string,
+    shouldDeleteIntegrationSecrets: boolean,
+    cb: () => void
+  ) => {
+    try {
+      await deleteIntegration({ id: integrationId, workspaceId, shouldDeleteIntegrationSecrets });
+      if (cb) cb();
+      createNotification({
+        type: "success",
+        text: "Deleted integration"
+      });
+    } catch (err) {
+      console.log(err);
+      createNotification({
+        type: "error",
+        text: "Failed to delete integration"
+      });
+    }
+  };
+
+  const handleIntegrationAuthRevoke = async (provider: string, cb?: () => void) => {
+    const integrationAuthForProvider = integrationAuths?.[provider];
+    if (!integrationAuthForProvider) return;
+
+    try {
+      await deleteIntegrationAuths({
+        integration: provider,
+        workspaceId
+      });
+      if (cb) cb();
+      createNotification({
+        type: "success",
+        text: "Revoked provider authentication"
+      });
+    } catch (err) {
+      console.error(err);
+      createNotification({
+        type: "error",
+        text: "Failed to revoke provider authentication"
+      });
+    }
+  };
+
+  const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
+    "deleteConfirmation",
+    "deleteSecretsConfirmation"
+  ] as const);
+
+  const [view, setView] = useState<IntegrationView>(IntegrationView.List);
+
+  const [shouldDeleteSecrets, setShouldDeleteSecrets] = useToggle(false);
+
+  if (isIntegrationLoading || isCloudIntegrationsLoading)
+    return (
+      <div className="flex h-[60vh] flex-col items-center justify-center gap-2">
+        <Spinner />
+      </div>
+    );
+
+  return (
+    <>
+      {view === IntegrationView.List ? (
+        <div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
+          <div className="mb-4 flex items-center justify-between">
+            <p className="text-xl font-semibold text-mineshaft-100">Native Integrations</p>
+            <Button
+              colorSchema="secondary"
+              type="submit"
+              leftIcon={<FontAwesomeIcon icon={faPlus} />}
+              onClick={() => setView(IntegrationView.New)}
+            >
+              Add Integration
+            </Button>
+          </div>
+          <IntegrationsTable
+            cloudIntegrations={cloudIntegrations}
+            integrations={integrations}
+            isLoading={isIntegrationLoading}
+            workspaceId={workspaceId}
+            environments={environments}
+            onDeleteIntegration={(integration) => {
+              setShouldDeleteSecrets.off();
+              handlePopUpOpen("deleteConfirmation", integration);
+            }}
+          />
+        </div>
+      ) : (
+        <CloudIntegrationSection
+          onIntegrationStart={handleProviderIntegrationStart}
+          onIntegrationRevoke={handleIntegrationAuthRevoke}
+          integrationAuths={integrationAuths}
+          cloudIntegrations={cloudIntegrations}
+          isLoading={isIntegrationAuthLoading || isCloudIntegrationsLoading}
+          onViewActiveIntegrations={() => setView(IntegrationView.List)}
+        />
+      )}
+      <DeleteActionModal
+        isOpen={popUp.deleteConfirmation.isOpen}
+        title={`Are you sure want to remove ${
+          (popUp?.deleteConfirmation.data as TIntegration)?.integration || " "
+        } integration for ${
+          (popUp?.deleteConfirmation.data as TIntegration)?.app || "this project"
+        }?`}
+        onChange={(isOpen) => handlePopUpToggle("deleteConfirmation", isOpen)}
+        deleteKey={
+          ((popUp?.deleteConfirmation?.data as TIntegration)?.integration ===
+            "azure-app-configuration" &&
+            (popUp?.deleteConfirmation?.data as TIntegration)?.app
+              ?.split("//")[1]
+              ?.split(".")[0]) ||
+          (popUp?.deleteConfirmation?.data as TIntegration)?.app ||
+          (popUp?.deleteConfirmation?.data as TIntegration)?.owner ||
+          (popUp?.deleteConfirmation?.data as TIntegration)?.path ||
+          (popUp?.deleteConfirmation?.data as TIntegration)?.integration ||
+          ""
+        }
+        onDeleteApproved={async () => {
+          if (shouldDeleteSecrets) {
+            handlePopUpOpen("deleteSecretsConfirmation");
+            return;
+          }
+
+          await handleIntegrationDelete(
+            (popUp?.deleteConfirmation.data as TIntegration).id,
+            false,
+            () => handlePopUpClose("deleteConfirmation")
+          );
+        }}
+      >
+        {(popUp?.deleteConfirmation?.data as TIntegration)?.integration === "github" && (
+          <div className="mt-4">
+            <Checkbox
+              id="delete-integration-secrets"
+              checkIndicatorBg="text-white"
+              onCheckedChange={() => setShouldDeleteSecrets.toggle()}
+            >
+              Delete previously synced secrets from the destination
+            </Checkbox>
+          </div>
+        )}
+      </DeleteActionModal>
+      <DeleteActionModal
+        isOpen={popUp.deleteSecretsConfirmation.isOpen}
+        title={`Are you sure you also want to delete secrets on ${
+          (popUp?.deleteConfirmation.data as TIntegration)?.integration
+        }?`}
+        subTitle="By confirming, you acknowledge that all secrets managed by this integration will be removed from the destination. This action is irreversible."
+        onChange={(isOpen) => handlePopUpToggle("deleteSecretsConfirmation", isOpen)}
+        deleteKey="confirm"
+        onDeleteApproved={async () => {
+          await handleIntegrationDelete(
+            (popUp?.deleteConfirmation.data as TIntegration).id,
+            true,
+            () => {
+              handlePopUpClose("deleteSecretsConfirmation");
+              handlePopUpClose("deleteConfirmation");
+            }
+          );
+        }}
+      />
+    </>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/index.ts b/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/index.ts
new file mode 100644
index 0000000000..cc5435f44c
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/index.ts
@@ -0,0 +1 @@
+export * from "./NativeIntegrationsTab";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/AwsParameterStoreSyncDestinationCol.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/AwsParameterStoreSyncDestinationCol.tsx
new file mode 100644
index 0000000000..32e1f8af82
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/AwsParameterStoreSyncDestinationCol.tsx
@@ -0,0 +1,14 @@
+import { TAwsParameterStoreSync } from "@app/hooks/api/secretSyncs/types/aws-parameter-store-sync";
+
+import { getSecretSyncDestinationColValues } from "../helpers";
+import { SecretSyncTableCell } from "../SecretSyncTableCell";
+
+type Props = {
+  secretSync: TAwsParameterStoreSync;
+};
+
+export const AwsParameterStoreSyncDestinationCol = ({ secretSync }: Props) => {
+  const { primaryText, secondaryText } = getSecretSyncDestinationColValues(secretSync);
+
+  return <SecretSyncTableCell primaryText={primaryText} secondaryText={secondaryText} />;
+};
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/GitHubSyncDestinationCol.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/GitHubSyncDestinationCol.tsx
new file mode 100644
index 0000000000..5c1b22fb1f
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/GitHubSyncDestinationCol.tsx
@@ -0,0 +1,49 @@
+import { GitHubSyncSelectedRepositoriesTooltipContent } from "@app/components/secret-syncs/github";
+import {
+  GitHubSyncScope,
+  GitHubSyncVisibility,
+  TGitHubSync
+} from "@app/hooks/api/secretSyncs/types/github-sync";
+
+import { getSecretSyncDestinationColValues } from "../helpers";
+import { SecretSyncTableCell, SecretSyncTableCellProps } from "../SecretSyncTableCell";
+
+type Props = {
+  secretSync: TGitHubSync;
+};
+
+export const GitHubSyncDestinationCol = ({ secretSync }: Props) => {
+  const { primaryText, secondaryText } = getSecretSyncDestinationColValues(secretSync);
+
+  const { destinationConfig } = secretSync;
+
+  let additionalProps: Pick<
+    SecretSyncTableCellProps,
+    "additionalTooltipContent" | "infoBadge" | "secondaryClassName"
+  > = {};
+
+  if (
+    destinationConfig.scope === GitHubSyncScope.Organization &&
+    destinationConfig.visibility === GitHubSyncVisibility.Selected
+  ) {
+    additionalProps = {
+      infoBadge: "secondary",
+      additionalTooltipContent: (
+        <div className="mt-4">
+          <GitHubSyncSelectedRepositoriesTooltipContent secretSync={secretSync} />
+        </div>
+      )
+    };
+  }
+
+  return (
+    <SecretSyncTableCell
+      primaryText={primaryText}
+      secondaryText={secondaryText}
+      {...additionalProps}
+      secondaryClassName={
+        destinationConfig.scope === GitHubSyncScope.Organization ? "capitalize" : undefined
+      }
+    />
+  );
+};
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx
new file mode 100644
index 0000000000..fcbe00cfe9
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx
@@ -0,0 +1,21 @@
+import { SecretSync, TSecretSync } from "@app/hooks/api/secretSyncs";
+
+import { AwsParameterStoreSyncDestinationCol } from "./AwsParameterStoreSyncDestinationCol";
+import { GitHubSyncDestinationCol } from "./GitHubSyncDestinationCol";
+
+type Props = {
+  secretSync: TSecretSync;
+};
+
+export const SecretSyncDestinationCol = ({ secretSync }: Props) => {
+  switch (secretSync.destination) {
+    case SecretSync.AWSParameterStore:
+      return <AwsParameterStoreSyncDestinationCol secretSync={secretSync} />;
+    case SecretSync.GitHub:
+      return <GitHubSyncDestinationCol secretSync={secretSync} />;
+    default:
+      throw new Error(
+        `Unhandled Secret Sync Destination Col: ${(secretSync as TSecretSync).destination}`
+      );
+  }
+};
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/index.ts b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/index.ts
new file mode 100644
index 0000000000..9d07687984
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/index.ts
@@ -0,0 +1 @@
+export * from "./SecretSyncDestinationCol";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncRow.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncRow.tsx
new file mode 100644
index 0000000000..3ef92d09ab
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncRow.tsx
@@ -0,0 +1,395 @@
+import { useCallback, useMemo } from "react";
+import {
+  faBan,
+  faCalendarCheck,
+  faCheck,
+  faCopy,
+  faDownload,
+  faEllipsisV,
+  faEraser,
+  faInfoCircle,
+  faRotate,
+  faToggleOff,
+  faToggleOn,
+  faTrash,
+  faTriangleExclamation,
+  faXmark
+} from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { useNavigate } from "@tanstack/react-router";
+import { format } from "date-fns";
+import { twMerge } from "tailwind-merge";
+
+import { createNotification } from "@app/components/notifications";
+import { ProjectPermissionCan } from "@app/components/permissions";
+import {
+  SecretSyncImportStatusBadge,
+  SecretSyncRemoveStatusBadge,
+  SecretSyncStatusBadge
+} from "@app/components/secret-syncs";
+import {
+  Badge,
+  DropdownMenu,
+  DropdownMenuContent,
+  DropdownMenuItem,
+  DropdownMenuTrigger,
+  IconButton,
+  Td,
+  Tooltip,
+  Tr
+} from "@app/components/v2";
+import { ROUTE_PATHS } from "@app/const/routes";
+import { ProjectPermissionSub } from "@app/context";
+import { ProjectPermissionSecretSyncActions } from "@app/context/ProjectPermissionContext/types";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { useToggle } from "@app/hooks";
+import { SecretSyncStatus, TSecretSync, useSecretSyncOption } from "@app/hooks/api/secretSyncs";
+
+import { SecretSyncDestinationCol } from "./SecretSyncDestinationCol";
+import { SecretSyncTableCell } from "./SecretSyncTableCell";
+
+type Props = {
+  secretSync: TSecretSync;
+  onDelete: (secretSync: TSecretSync) => void;
+  onTriggerSyncSecrets: (secretSync: TSecretSync) => void;
+  onTriggerImportSecrets: (secretSync: TSecretSync) => void;
+  onTriggerRemoveSecrets: (secretSync: TSecretSync) => void;
+  onToggleEnable: (secretSync: TSecretSync) => void;
+};
+
+export const SecretSyncRow = ({
+  secretSync,
+  onDelete,
+  onTriggerSyncSecrets,
+  onTriggerImportSecrets,
+  onTriggerRemoveSecrets,
+  onToggleEnable
+}: Props) => {
+  const navigate = useNavigate();
+  const {
+    id,
+    folder,
+    lastSyncMessage,
+    destination,
+    lastSyncedAt,
+    environment,
+    name,
+    description,
+    syncStatus,
+    isAutoSyncEnabled,
+    projectId
+  } = secretSync;
+
+  const { syncOption } = useSecretSyncOption(destination);
+
+  const destinationName = SECRET_SYNC_MAP[destination].name;
+
+  const [isIdCopied, setIsIdCopied] = useToggle(false);
+
+  const handleCopyId = useCallback(() => {
+    setIsIdCopied.on();
+    navigator.clipboard.writeText(id);
+
+    createNotification({
+      text: "Secret Sync ID copied to clipboard",
+      type: "info"
+    });
+
+    const timer = setTimeout(() => setIsIdCopied.off(), 2000);
+
+    // eslint-disable-next-line consistent-return
+    return () => clearTimeout(timer);
+  }, [isIdCopied]);
+
+  const failureMessage = useMemo(() => {
+    if (syncStatus === SecretSyncStatus.Failed) {
+      if (lastSyncMessage)
+        try {
+          return JSON.stringify(JSON.parse(lastSyncMessage), null, 2);
+        } catch {
+          return lastSyncMessage;
+        }
+
+      return "An Unknown Error Occurred.";
+    }
+    return null;
+  }, [syncStatus, lastSyncMessage]);
+
+  const destinationDetails = SECRET_SYNC_MAP[destination];
+
+  return (
+    <Tr
+      onClick={() =>
+        navigate({
+          to: ROUTE_PATHS.SecretManager.SecretSyncDetailsByIDPage.path,
+          params: {
+            syncId: id,
+            destination,
+            projectId
+          }
+        })
+      }
+      className={twMerge(
+        "group h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700",
+        syncStatus === SecretSyncStatus.Failed && "bg-red/5 hover:bg-red/10"
+      )}
+      key={`sync-${id}`}
+    >
+      <Td>
+        <img
+          alt={`${destinationDetails.name} sync`}
+          src={`/images/integrations/${destinationDetails.image}`}
+          className="min-w-[1.75rem]"
+        />
+      </Td>
+      <Td className="!min-w-[8rem] max-w-0">
+        <div>
+          <div className="flex w-full items-center">
+            <p className="truncate">{name}</p>
+            {description && (
+              <Tooltip content={description}>
+                <FontAwesomeIcon
+                  icon={faInfoCircle}
+                  size="xs"
+                  className="ml-1 text-mineshaft-400"
+                />
+              </Tooltip>
+            )}
+          </div>
+          <p className="truncate text-xs leading-4 text-bunker-300">{destinationDetails.name}</p>
+        </div>
+      </Td>
+      {folder && environment ? (
+        <SecretSyncTableCell primaryText={folder.path} secondaryText={environment.name} />
+      ) : (
+        <Td>
+          <Tooltip content="The source location for this sync has been deleted. Configure a new source or remove this sync.">
+            <div className="w-min">
+              <Badge
+                className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap"
+                variant="primary"
+              >
+                <FontAwesomeIcon icon={faTriangleExclamation} />
+                <span>Source Folder Deleted</span>
+              </Badge>
+            </div>
+          </Tooltip>
+        </Td>
+      )}
+      <SecretSyncDestinationCol secretSync={secretSync} />
+      <Td>
+        <div className="flex items-center gap-1">
+          {syncStatus && (
+            <Tooltip
+              position="left"
+              className="max-w-sm"
+              content={
+                [SecretSyncStatus.Succeeded, SecretSyncStatus.Failed].includes(syncStatus) ? (
+                  <div className="flex flex-col gap-2 whitespace-normal py-1">
+                    {lastSyncedAt && (
+                      <div>
+                        <div
+                          className={`mb-2 flex self-start ${syncStatus === SecretSyncStatus.Failed ? "text-yellow" : "text-green"}`}
+                        >
+                          <FontAwesomeIcon
+                            icon={faCalendarCheck}
+                            className="ml-1 pr-1.5 pt-0.5 text-sm"
+                          />
+                          <div className="text-xs">Last Synced</div>
+                        </div>
+                        <div className="rounded bg-mineshaft-600 p-2 text-xs">
+                          {format(new Date(lastSyncedAt), "yyyy-MM-dd, hh:mm aaa")}
+                        </div>
+                      </div>
+                    )}
+                    {failureMessage && (
+                      <div>
+                        <div className="mb-2 flex self-start text-red">
+                          <FontAwesomeIcon icon={faXmark} className="ml-1 pr-1.5 pt-0.5 text-sm" />
+                          <div className="text-xs">Failure Reason</div>
+                        </div>
+                        <div className="rounded bg-mineshaft-600 p-2 text-xs">{failureMessage}</div>
+                      </div>
+                    )}
+                  </div>
+                ) : undefined
+              }
+            >
+              <div>
+                <SecretSyncStatusBadge status={syncStatus} />
+              </div>
+            </Tooltip>
+          )}
+          {!isAutoSyncEnabled && (
+            <Tooltip
+              className="text-xs"
+              content="Auto-Sync is disabled. Changes to the source location will not be automatically synced to the destination."
+            >
+              <div>
+                <Badge className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap bg-mineshaft-400/50 text-bunker-300">
+                  <FontAwesomeIcon icon={faBan} />
+                  {!syncStatus && "Auto-Sync Disabled"}
+                </Badge>
+              </div>
+            </Tooltip>
+          )}
+          <SecretSyncImportStatusBadge mini secretSync={secretSync} />
+          <SecretSyncRemoveStatusBadge mini secretSync={secretSync} />
+        </div>
+      </Td>
+      <Td>
+        <Tooltip className="max-w-sm text-center" content="Options">
+          <DropdownMenu>
+            <DropdownMenuTrigger asChild>
+              <IconButton
+                ariaLabel="Options"
+                colorSchema="secondary"
+                className="w-6"
+                variant="plain"
+              >
+                <FontAwesomeIcon icon={faEllipsisV} />
+              </IconButton>
+            </DropdownMenuTrigger>
+            <DropdownMenuContent align="end">
+              <DropdownMenuItem
+                icon={<FontAwesomeIcon icon={isIdCopied ? faCheck : faCopy} />}
+                onClick={(e) => {
+                  e.stopPropagation();
+                  handleCopyId();
+                }}
+              >
+                Copy Sync ID
+              </DropdownMenuItem>
+              <ProjectPermissionCan
+                I={ProjectPermissionSecretSyncActions.SyncSecrets}
+                a={ProjectPermissionSub.SecretSyncs}
+              >
+                {(isAllowed: boolean) => (
+                  <DropdownMenuItem
+                    icon={<FontAwesomeIcon icon={faRotate} />}
+                    onClick={(e) => {
+                      e.stopPropagation();
+                      onTriggerSyncSecrets(secretSync);
+                    }}
+                    isDisabled={!isAllowed}
+                  >
+                    <Tooltip
+                      position="left"
+                      sideOffset={42}
+                      content={`Manually trigger a sync for this ${destinationName} destination.`}
+                    >
+                      <div className="flex h-full w-full items-center justify-between gap-1">
+                        <span> Trigger Sync</span>
+                        <FontAwesomeIcon
+                          className="text-bunker-300"
+                          size="sm"
+                          icon={faInfoCircle}
+                        />
+                      </div>
+                    </Tooltip>
+                  </DropdownMenuItem>
+                )}
+              </ProjectPermissionCan>
+              {syncOption?.canImportSecrets && (
+                <ProjectPermissionCan
+                  I={ProjectPermissionSecretSyncActions.ImportSecrets}
+                  a={ProjectPermissionSub.SecretSyncs}
+                >
+                  {(isAllowed: boolean) => (
+                    <DropdownMenuItem
+                      icon={<FontAwesomeIcon icon={faDownload} />}
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        onTriggerImportSecrets(secretSync);
+                      }}
+                      isDisabled={!isAllowed}
+                    >
+                      <Tooltip
+                        position="left"
+                        sideOffset={42}
+                        content={`Import secrets from this ${destinationName} destination into Infisical.`}
+                      >
+                        <div className="flex h-full w-full items-center justify-between gap-1">
+                          <span>Import Secrets</span>
+                          <FontAwesomeIcon
+                            className="text-bunker-300"
+                            size="sm"
+                            icon={faInfoCircle}
+                          />
+                        </div>
+                      </Tooltip>
+                    </DropdownMenuItem>
+                  )}
+                </ProjectPermissionCan>
+              )}
+              <ProjectPermissionCan
+                I={ProjectPermissionSecretSyncActions.RemoveSecrets}
+                a={ProjectPermissionSub.SecretSyncs}
+              >
+                {(isAllowed: boolean) => (
+                  <DropdownMenuItem
+                    icon={<FontAwesomeIcon icon={faEraser} />}
+                    onClick={(e) => {
+                      e.stopPropagation();
+                      onTriggerRemoveSecrets(secretSync);
+                    }}
+                    isDisabled={!isAllowed}
+                  >
+                    <Tooltip
+                      position="left"
+                      sideOffset={42}
+                      content={`Remove secrets synced by Infisical from this ${destinationName} destination.`}
+                    >
+                      <div className="flex h-full w-full items-center justify-between gap-1">
+                        <span>Remove Secrets</span>
+                        <FontAwesomeIcon
+                          className="text-bunker-300"
+                          size="sm"
+                          icon={faInfoCircle}
+                        />
+                      </div>
+                    </Tooltip>
+                  </DropdownMenuItem>
+                )}
+              </ProjectPermissionCan>
+              <ProjectPermissionCan
+                I={ProjectPermissionSecretSyncActions.Edit}
+                a={ProjectPermissionSub.SecretSyncs}
+              >
+                {(isAllowed: boolean) => (
+                  <DropdownMenuItem
+                    isDisabled={!isAllowed}
+                    icon={<FontAwesomeIcon icon={isAutoSyncEnabled ? faToggleOff : faToggleOn} />}
+                    onClick={(e) => {
+                      e.stopPropagation();
+                      onToggleEnable(secretSync);
+                    }}
+                  >
+                    {isAutoSyncEnabled ? "Disable" : "Enable"} Auto-Sync
+                  </DropdownMenuItem>
+                )}
+              </ProjectPermissionCan>
+              <ProjectPermissionCan
+                I={ProjectPermissionSecretSyncActions.Delete}
+                a={ProjectPermissionSub.SecretSyncs}
+              >
+                {(isAllowed: boolean) => (
+                  <DropdownMenuItem
+                    isDisabled={!isAllowed}
+                    icon={<FontAwesomeIcon icon={faTrash} />}
+                    onClick={(e) => {
+                      e.stopPropagation();
+                      onDelete(secretSync);
+                    }}
+                  >
+                    Delete Sync
+                  </DropdownMenuItem>
+                )}
+              </ProjectPermissionCan>
+            </DropdownMenuContent>
+          </DropdownMenu>
+        </Tooltip>
+      </Td>
+    </Tr>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncTableCell.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncTableCell.tsx
new file mode 100644
index 0000000000..6f42c1f0e9
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncTableCell.tsx
@@ -0,0 +1,67 @@
+import { ReactNode } from "react";
+import { faInfoCircle } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { twMerge } from "tailwind-merge";
+
+import { Td, Tooltip } from "@app/components/v2";
+
+export type SecretSyncTableCellProps = {
+  primaryText: string;
+  secondaryText?: string;
+  infoBadge?: "primary" | "secondary";
+  additionalTooltipContent?: ReactNode;
+  primaryClassName?: string;
+  secondaryClassName?: string;
+};
+
+export const SecretSyncTableCell = ({
+  primaryText,
+  secondaryText,
+  infoBadge,
+  additionalTooltipContent,
+  primaryClassName,
+  secondaryClassName
+}: SecretSyncTableCellProps) => {
+  return (
+    <Td className="!min-w-[8rem] max-w-0">
+      <Tooltip
+        side="left"
+        className="max-w-2xl break-words"
+        content={
+          <>
+            <p className="text-sm">{primaryText}</p>
+            {secondaryText && <p className="text-xs leading-3 text-bunker-300">{secondaryText}</p>}
+            {additionalTooltipContent}
+          </>
+        }
+      >
+        <div>
+          <p className={twMerge("truncate text-sm", primaryClassName)}>
+            {primaryText}
+            {infoBadge === "primary" && (
+              <FontAwesomeIcon
+                size="xs"
+                icon={faInfoCircle}
+                className="ml-1 inline-block text-bunker-300"
+              />
+            )}
+          </p>
+          {secondaryText && (
+            <p
+              className={twMerge("truncate text-xs leading-4 text-bunker-300", secondaryClassName)}
+            >
+              {secondaryText}
+              {infoBadge === "secondary" && (
+                <FontAwesomeIcon
+                  size="xs"
+                  icon={faInfoCircle}
+                  className="ml-1 inline-block text-bunker-300"
+                />
+              )}
+            </p>
+          )}
+        </div>
+      </Tooltip>
+    </Td>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncsTable.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncsTable.tsx
new file mode 100644
index 0000000000..a5e7d270d4
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncsTable.tsx
@@ -0,0 +1,495 @@
+import { useMemo, useState } from "react";
+import {
+  faArrowDown,
+  faArrowUp,
+  faCheck,
+  faCheckCircle,
+  faFilter,
+  faMagnifyingGlass,
+  faRotate,
+  faSearch,
+  faWarning
+} from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { twMerge } from "tailwind-merge";
+
+import { createNotification } from "@app/components/notifications";
+import {
+  DeleteSecretSyncModal,
+  SecretSyncImportSecretsModal,
+  SecretSyncRemoveSecretsModal
+} from "@app/components/secret-syncs";
+import {
+  DropdownMenu,
+  DropdownMenuContent,
+  DropdownMenuItem,
+  DropdownMenuLabel,
+  DropdownMenuTrigger,
+  EmptyState,
+  IconButton,
+  Input,
+  Pagination,
+  Table,
+  TableContainer,
+  TBody,
+  Th,
+  THead,
+  Tr
+} from "@app/components/v2";
+import { useWorkspace } from "@app/context";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { usePagination, usePopUp, useResetPageHelper } from "@app/hooks";
+import { OrderByDirection } from "@app/hooks/api/generic/types";
+import {
+  SecretSync,
+  SecretSyncStatus,
+  TSecretSync,
+  useTriggerSecretSyncSyncSecrets,
+  useUpdateSecretSync
+} from "@app/hooks/api/secretSyncs";
+
+import { getSecretSyncDestinationColValues } from "./helpers";
+import { SecretSyncRow } from "./SecretSyncRow";
+
+enum SecretSyncsOrderBy {
+  Destination = "destination",
+  Source = "source",
+  Name = "name",
+  Status = "status"
+}
+
+type SecretSyncFilters = {
+  destinations: SecretSync[];
+  status: SecretSyncStatus[];
+  environmentIds: string[];
+};
+
+const getSyncStatusOrderValue = (syncStatus: SecretSyncStatus | null) => {
+  switch (syncStatus) {
+    case SecretSyncStatus.Failed:
+      return 0;
+    case SecretSyncStatus.Pending:
+    case SecretSyncStatus.Running:
+      return 1;
+    case SecretSyncStatus.Succeeded:
+      return 2;
+    default:
+      return 3;
+  }
+};
+
+type Props = {
+  secretSyncs: TSecretSync[];
+};
+
+const STATUS_ICON_MAP = {
+  [SecretSyncStatus.Succeeded]: { icon: faCheck, className: "text-green", name: "Synced" },
+  [SecretSyncStatus.Failed]: { icon: faWarning, className: "text-red", name: "Not Synced" },
+  [SecretSyncStatus.Pending]: { icon: faRotate, className: "text-yellow", name: "Syncing" },
+  [SecretSyncStatus.Running]: { icon: faRotate, className: "text-yellow", name: "Syncing" }
+};
+
+export const SecretSyncsTable = ({ secretSyncs }: Props) => {
+  const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
+    "deleteSync",
+    "importSecrets",
+    "removeSecrets"
+  ] as const);
+  const triggerSync = useTriggerSecretSyncSyncSecrets();
+  const updateSync = useUpdateSecretSync();
+
+  const [filters, setFilters] = useState<SecretSyncFilters>({
+    destinations: [],
+    status: [],
+    environmentIds: []
+  });
+
+  const { currentWorkspace } = useWorkspace();
+
+  const {
+    search,
+    setSearch,
+    setPage,
+    page,
+    perPage,
+    setPerPage,
+    offset,
+    orderDirection,
+    toggleOrderDirection,
+    orderBy,
+    setOrderDirection,
+    setOrderBy
+  } = usePagination<SecretSyncsOrderBy>(SecretSyncsOrderBy.Name, { initPerPage: 20 });
+
+  const filteredSecretSyncs = useMemo(
+    () =>
+      secretSyncs
+        .filter((secretSync) => {
+          const { destination, name, connection, folder, environment, syncStatus } = secretSync;
+
+          if (filters.destinations.length && !filters.destinations.includes(destination))
+            return false;
+
+          if (
+            filters.environmentIds.length &&
+            environment?.id &&
+            !filters.environmentIds.includes(environment.id)
+          )
+            return false;
+
+          if (filters.status.length && (!syncStatus || !filters.status.includes(syncStatus))) {
+            return false;
+          }
+
+          const searchValue = search.trim().toLowerCase();
+
+          const destinationValues = getSecretSyncDestinationColValues(secretSync);
+
+          return (
+            SECRET_SYNC_MAP[destination].name.toLowerCase().includes(searchValue) ||
+            name.toLowerCase().includes(searchValue) ||
+            folder?.path.toLowerCase().includes(searchValue) ||
+            environment?.name.toLowerCase().includes(searchValue) ||
+            connection.name.toLowerCase().includes(searchValue) ||
+            destinationValues.primaryText.toLowerCase().includes(searchValue) ||
+            destinationValues.secondaryText?.toLowerCase().includes(searchValue)
+          );
+        })
+        .sort((a, b) => {
+          const [syncOne, syncTwo] = orderDirection === OrderByDirection.ASC ? [a, b] : [b, a];
+
+          switch (orderBy) {
+            case SecretSyncsOrderBy.Source:
+              return (syncOne.folder?.path ?? "")
+                .toLowerCase()
+                .localeCompare(syncTwo.folder?.path.toLowerCase() ?? "");
+            case SecretSyncsOrderBy.Destination:
+              return getSecretSyncDestinationColValues(syncOne)
+                .primaryText.toLowerCase()
+                .localeCompare(
+                  getSecretSyncDestinationColValues(syncTwo).primaryText.toLowerCase()
+                );
+            case SecretSyncsOrderBy.Status:
+              if (!syncOne.syncStatus && syncTwo.syncStatus) return 1;
+              if (syncOne.syncStatus && !syncTwo.syncStatus) return -1;
+              if (!syncOne.syncStatus && !syncTwo.syncStatus) return 0;
+
+              return (
+                getSyncStatusOrderValue(syncOne.syncStatus) -
+                getSyncStatusOrderValue(syncTwo.syncStatus)
+              );
+            case SecretSyncsOrderBy.Name:
+            default:
+              return syncOne.name.toLowerCase().localeCompare(syncTwo.name.toLowerCase());
+          }
+        }),
+    [secretSyncs, orderDirection, search, orderBy, filters]
+  );
+
+  useResetPageHelper({
+    totalCount: filteredSecretSyncs.length,
+    offset,
+    setPage
+  });
+
+  const handleSort = (column: SecretSyncsOrderBy) => {
+    if (column === orderBy) {
+      toggleOrderDirection();
+      return;
+    }
+
+    setOrderBy(column);
+    setOrderDirection(OrderByDirection.ASC);
+  };
+
+  const getClassName = (col: SecretSyncsOrderBy) =>
+    twMerge("ml-2", orderBy === col ? "" : "opacity-30");
+
+  const getColSortIcon = (col: SecretSyncsOrderBy) =>
+    orderDirection === OrderByDirection.DESC && orderBy === col ? faArrowUp : faArrowDown;
+
+  const isTableFiltered = Boolean(filters.destinations.length);
+
+  const handleDelete = (secretSync: TSecretSync) => handlePopUpOpen("deleteSync", secretSync);
+
+  const handleTriggerImportSecrets = (secretSync: TSecretSync) =>
+    handlePopUpOpen("importSecrets", secretSync);
+
+  const handleTriggerRemoveSecrets = (secretSync: TSecretSync) =>
+    handlePopUpOpen("removeSecrets", secretSync);
+
+  const handleToggleEnableSync = async (secretSync: TSecretSync) => {
+    const destinationName = SECRET_SYNC_MAP[secretSync.destination].name;
+
+    const isAutoSyncEnabled = !secretSync.isAutoSyncEnabled;
+
+    try {
+      await updateSync.mutateAsync({
+        syncId: secretSync.id,
+        destination: secretSync.destination,
+        isAutoSyncEnabled
+      });
+
+      createNotification({
+        text: `Successfully ${isAutoSyncEnabled ? "enabled" : "disabled"} auto-sync for ${destinationName} Sync`,
+        type: "success"
+      });
+    } catch {
+      createNotification({
+        text: `Failed to ${isAutoSyncEnabled ? "enable" : "disable"} auto-sync for ${destinationName} Sync`,
+        type: "error"
+      });
+    }
+  };
+
+  const handleTriggerSync = async (secretSync: TSecretSync) => {
+    const destinationName = SECRET_SYNC_MAP[secretSync.destination].name;
+
+    try {
+      await triggerSync.mutateAsync({
+        syncId: secretSync.id,
+        destination: secretSync.destination
+      });
+
+      createNotification({
+        text: `Successfully triggered ${destinationName} Sync`,
+        type: "success"
+      });
+    } catch {
+      createNotification({
+        text: `Failed to trigger ${destinationName} Sync`,
+        type: "error"
+      });
+    }
+  };
+
+  return (
+    <div>
+      <div className="flex gap-2">
+        <Input
+          value={search}
+          onChange={(e) => setSearch(e.target.value)}
+          leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
+          placeholder="Search secret syncs..."
+          className="flex-1"
+        />
+        <DropdownMenu>
+          <DropdownMenuTrigger asChild>
+            <IconButton
+              ariaLabel="Filter secret syncs"
+              variant="plain"
+              size="sm"
+              className={twMerge(
+                "flex h-10 w-11 items-center justify-center overflow-hidden border border-mineshaft-600 bg-mineshaft-800 p-0 transition-all hover:border-primary/60 hover:bg-primary/10",
+                isTableFiltered && "border-primary/50 text-primary"
+              )}
+            >
+              <FontAwesomeIcon icon={faFilter} />
+            </IconButton>
+          </DropdownMenuTrigger>
+          <DropdownMenuContent className="thin-scrollbar max-h-[70vh] overflow-y-auto" align="end">
+            <DropdownMenuLabel>Status</DropdownMenuLabel>
+            {Object.values(SecretSyncStatus).map((status) => (
+              <DropdownMenuItem
+                onClick={(e) => {
+                  e.preventDefault();
+                  setFilters((prev) => ({
+                    ...prev,
+                    status: prev.status.includes(status)
+                      ? prev.status.filter((s) => s !== status)
+                      : [...prev.status, status]
+                  }));
+                }}
+                key={status}
+                icon={
+                  filters.status.includes(status) && (
+                    <FontAwesomeIcon className="text-primary" icon={faCheckCircle} />
+                  )
+                }
+                iconPos="right"
+              >
+                <div className="flex items-center gap-2">
+                  <FontAwesomeIcon
+                    icon={STATUS_ICON_MAP[status].icon}
+                    className={STATUS_ICON_MAP[status].className}
+                  />
+                  <span className="capitalize">{STATUS_ICON_MAP[status].name}</span>
+                </div>
+              </DropdownMenuItem>
+            ))}
+            <DropdownMenuLabel>Service</DropdownMenuLabel>
+            {secretSyncs.length ? (
+              [...new Set(secretSyncs.map(({ destination }) => destination))].map((destination) => {
+                const { name, image } = SECRET_SYNC_MAP[destination];
+
+                return (
+                  <DropdownMenuItem
+                    onClick={(e) => {
+                      e.preventDefault();
+                      setFilters((prev) => ({
+                        ...prev,
+                        destinations: prev.destinations.includes(destination)
+                          ? prev.destinations.filter((a) => a !== destination)
+                          : [...prev.destinations, destination]
+                      }));
+                    }}
+                    key={destination}
+                    icon={
+                      filters.destinations.includes(destination) && (
+                        <FontAwesomeIcon className="text-primary" icon={faCheckCircle} />
+                      )
+                    }
+                    iconPos="right"
+                  >
+                    <div className="flex items-center gap-2">
+                      <img
+                        alt={`${name} integration`}
+                        src={`/images/integrations/${image}`}
+                        className="h-4 w-4"
+                      />
+                      <span>{name}</span>
+                    </div>
+                  </DropdownMenuItem>
+                );
+              })
+            ) : (
+              <DropdownMenuItem isDisabled>No Secret Syncs Configured</DropdownMenuItem>
+            )}
+            <DropdownMenuLabel>Environment</DropdownMenuLabel>
+            {currentWorkspace.environments.map((env) => (
+              <DropdownMenuItem
+                onClick={(e) => {
+                  e.preventDefault();
+                  setFilters((prev) => ({
+                    ...prev,
+                    environmentIds: prev.environmentIds.includes(env.id)
+                      ? prev.environmentIds.filter((i) => i !== env.id)
+                      : [...prev.environmentIds, env.id]
+                  }));
+                }}
+                key={env.id}
+                icon={
+                  filters.environmentIds.includes(env.id) && (
+                    <FontAwesomeIcon className="text-primary" icon={faCheckCircle} />
+                  )
+                }
+                iconPos="right"
+              >
+                <span className="capitalize">{env.name}</span>
+              </DropdownMenuItem>
+            ))}
+          </DropdownMenuContent>
+        </DropdownMenu>
+      </div>
+      <TableContainer className="mt-4">
+        <Table>
+          <THead>
+            <Tr>
+              <Th className="w-2" />
+              <Th className="w-1/4">
+                <div className="flex items-center">
+                  Name
+                  <IconButton
+                    variant="plain"
+                    className={getClassName(SecretSyncsOrderBy.Name)}
+                    ariaLabel="sort"
+                    onClick={() => handleSort(SecretSyncsOrderBy.Name)}
+                  >
+                    <FontAwesomeIcon icon={getColSortIcon(SecretSyncsOrderBy.Name)} />
+                  </IconButton>
+                </div>
+              </Th>
+              <Th className="w-1/3">
+                <div className="flex items-center">
+                  Source
+                  <IconButton
+                    variant="plain"
+                    className={getClassName(SecretSyncsOrderBy.Source)}
+                    ariaLabel="sort"
+                    onClick={() => handleSort(SecretSyncsOrderBy.Source)}
+                  >
+                    <FontAwesomeIcon icon={getColSortIcon(SecretSyncsOrderBy.Source)} />
+                  </IconButton>
+                </div>
+              </Th>
+              <Th className="w-1/3">
+                <div className="flex items-center">
+                  Destination
+                  <IconButton
+                    variant="plain"
+                    className={getClassName(SecretSyncsOrderBy.Destination)}
+                    ariaLabel="sort"
+                    onClick={() => handleSort(SecretSyncsOrderBy.Destination)}
+                  >
+                    <FontAwesomeIcon icon={getColSortIcon(SecretSyncsOrderBy.Destination)} />
+                  </IconButton>
+                </div>
+              </Th>
+              <Th className="min-w-[10.5rem]">
+                <div className="flex items-center">
+                  Status
+                  <IconButton
+                    variant="plain"
+                    className={getClassName(SecretSyncsOrderBy.Status)}
+                    ariaLabel="sort"
+                    onClick={() => handleSort(SecretSyncsOrderBy.Status)}
+                  >
+                    <FontAwesomeIcon icon={getColSortIcon(SecretSyncsOrderBy.Status)} />
+                  </IconButton>
+                </div>
+              </Th>
+              <Th className="w-5" />
+            </Tr>
+          </THead>
+          <TBody>
+            {filteredSecretSyncs.slice(offset, perPage * page).map((secretSync) => (
+              <SecretSyncRow
+                key={secretSync.id}
+                secretSync={secretSync}
+                onDelete={handleDelete}
+                onTriggerSyncSecrets={handleTriggerSync}
+                onTriggerImportSecrets={handleTriggerImportSecrets}
+                onTriggerRemoveSecrets={handleTriggerRemoveSecrets}
+                onToggleEnable={handleToggleEnableSync}
+              />
+            ))}
+          </TBody>
+        </Table>
+        {Boolean(filteredSecretSyncs.length) && (
+          <Pagination
+            count={filteredSecretSyncs.length}
+            page={page}
+            perPage={perPage}
+            onChangePage={setPage}
+            onChangePerPage={setPerPage}
+          />
+        )}
+        {!filteredSecretSyncs?.length && (
+          <EmptyState
+            title={
+              secretSyncs.length
+                ? "No syncs match search..."
+                : "This project has no syncs configured"
+            }
+            icon={secretSyncs.length ? faSearch : faRotate}
+          />
+        )}
+      </TableContainer>
+      <DeleteSecretSyncModal
+        onOpenChange={(isOpen) => handlePopUpToggle("deleteSync", isOpen)}
+        isOpen={popUp.deleteSync.isOpen}
+        secretSync={popUp.deleteSync.data}
+      />
+      <SecretSyncImportSecretsModal
+        onOpenChange={(isOpen) => handlePopUpToggle("importSecrets", isOpen)}
+        isOpen={popUp.importSecrets.isOpen}
+        secretSync={popUp.importSecrets.data}
+      />
+      <SecretSyncRemoveSecretsModal
+        onOpenChange={(isOpen) => handlePopUpToggle("removeSecrets", isOpen)}
+        isOpen={popUp.removeSecrets.isOpen}
+        secretSync={popUp.removeSecrets.data}
+      />
+    </div>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts
new file mode 100644
index 0000000000..2b79015a05
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts
@@ -0,0 +1,50 @@
+import { SecretSync, TSecretSync } from "@app/hooks/api/secretSyncs";
+import {
+  GitHubSyncScope,
+  GitHubSyncVisibility
+} from "@app/hooks/api/secretSyncs/types/github-sync";
+
+// This functional ensures parity across what is displayed in the destination column
+// and the values used when search filtering
+export const getSecretSyncDestinationColValues = (secretSync: TSecretSync) => {
+  let primaryText: string;
+  let secondaryText: string | undefined;
+
+  const { destination, destinationConfig } = secretSync;
+
+  switch (destination) {
+    case SecretSync.AWSParameterStore:
+      primaryText = destinationConfig.path;
+      secondaryText = destinationConfig.region;
+      break;
+    case SecretSync.GitHub:
+      switch (destinationConfig.scope) {
+        case GitHubSyncScope.Organization:
+          primaryText = destinationConfig.org;
+          if (destinationConfig.visibility === GitHubSyncVisibility.Selected) {
+            secondaryText = `Organization - ${destinationConfig.selectedRepositoryIds?.length ?? 0} Repositories`;
+          } else {
+            secondaryText = `Organization - ${destinationConfig.visibility} Repositories`;
+          }
+          break;
+        case GitHubSyncScope.Repository:
+          primaryText = `${destinationConfig.owner}/${destinationConfig.repo}`;
+          secondaryText = "Repository";
+          break;
+        case GitHubSyncScope.RepositoryEnvironment:
+          primaryText = `${destinationConfig.owner}/${destinationConfig.repo}`;
+          secondaryText = `Environment - ${destinationConfig.env}`;
+          break;
+        default:
+          throw new Error(`Unhandled GitHub Scope Destination Col Values ${destination}`);
+      }
+      break;
+    default:
+      throw new Error(`Unhandled Destination Col Values ${destination}`);
+  }
+
+  return {
+    primaryText,
+    secondaryText
+  };
+};
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/index.ts b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/index.ts
new file mode 100644
index 0000000000..a1d3b8a4f2
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/index.ts
@@ -0,0 +1 @@
+export * from "./SecretSyncsTable";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncsTab.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncsTab.tsx
new file mode 100644
index 0000000000..f44ea439b5
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncsTab.tsx
@@ -0,0 +1,84 @@
+import { faArrowUpRightFromSquare, faBookOpen, faPlus } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { ProjectPermissionCan } from "@app/components/permissions";
+import { CreateSecretSyncModal } from "@app/components/secret-syncs";
+import { Button, Spinner } from "@app/components/v2";
+import { ProjectPermissionSub, useWorkspace } from "@app/context";
+import { ProjectPermissionSecretSyncActions } from "@app/context/ProjectPermissionContext/types";
+import { usePopUp } from "@app/hooks";
+import { useListSecretSyncs } from "@app/hooks/api/secretSyncs";
+
+import { SecretSyncsTable } from "./SecretSyncTable";
+
+export const SecretSyncsTab = () => {
+  const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["addSync"] as const);
+
+  const { currentWorkspace } = useWorkspace();
+
+  const { data: secretSyncs = [], isPending: isSecretSyncsPending } = useListSecretSyncs(
+    currentWorkspace.id,
+    {
+      refetchInterval: 4000
+    }
+  );
+
+  if (isSecretSyncsPending)
+    return (
+      <div className="flex h-[60vh] flex-col items-center justify-center gap-2">
+        <Spinner />
+      </div>
+    );
+
+  return (
+    <>
+      <div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
+        <div className="mb-4 flex items-center justify-between">
+          <div>
+            <div className="flex items-start gap-1">
+              <p className="text-xl font-semibold text-mineshaft-100">Secret Syncs</p>
+              <a
+                href="https://infisical.com/docs/integrations/secret-syncs/overview"
+                target="_blank"
+                rel="noopener noreferrer"
+              >
+                <div className="ml-1 mt-[0.32rem] inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
+                  <FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
+                  <span>Docs</span>
+                  <FontAwesomeIcon
+                    icon={faArrowUpRightFromSquare}
+                    className="mb-[0.07rem] ml-1.5 text-[10px]"
+                  />
+                </div>
+              </a>
+            </div>
+            <p className="text-sm text-bunker-300">
+              Use App Connections to sync secrets to third-party services.
+            </p>
+          </div>
+          <ProjectPermissionCan
+            I={ProjectPermissionSecretSyncActions.Create}
+            a={ProjectPermissionSub.SecretSyncs}
+          >
+            {(isAllowed) => (
+              <Button
+                colorSchema="secondary"
+                type="submit"
+                leftIcon={<FontAwesomeIcon icon={faPlus} />}
+                onClick={() => handlePopUpOpen("addSync")}
+                isDisabled={!isAllowed}
+              >
+                Add Sync
+              </Button>
+            )}
+          </ProjectPermissionCan>
+        </div>
+        <SecretSyncsTable secretSyncs={secretSyncs} />
+      </div>
+      <CreateSecretSyncModal
+        isOpen={popUp.addSync.isOpen}
+        onOpenChange={(isOpen) => handlePopUpToggle("addSync", isOpen)}
+      />
+    </>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/index.ts b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/index.ts
new file mode 100644
index 0000000000..74c03e1e4c
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/index.ts
@@ -0,0 +1 @@
+export * from "./SecretSyncsTab";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/index.ts b/frontend/src/pages/secret-manager/IntegrationsListPage/components/index.ts
new file mode 100644
index 0000000000..ba1b8d3d33
--- /dev/null
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/index.ts
@@ -0,0 +1,4 @@
+export * from "./FrameworkIntegrationTab";
+export * from "./InfrastructureIntegrationTab";
+export * from "./NativeIntegrationsTab";
+export * from "./SecretSyncsTab";
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/route.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/route.tsx
index bb0085aea0..5a176b2f95 100644
--- a/frontend/src/pages/secret-manager/IntegrationsListPage/route.tsx
+++ b/frontend/src/pages/secret-manager/IntegrationsListPage/route.tsx
@@ -1,11 +1,22 @@
 import { createFileRoute } from "@tanstack/react-router";
+import { zodValidator } from "@tanstack/zod-adapter";
+import { z } from "zod";
+
+import { IntegrationsListPageTabs } from "@app/types/integrations";
 
 import { IntegrationsListPage } from "./IntegrationsListPage";
 
+const IntegrationsListPageQuerySchema = z.object({
+  selectedTab: z
+    .nativeEnum(IntegrationsListPageTabs)
+    .catch(IntegrationsListPageTabs.NativeIntegrations)
+});
+
 export const Route = createFileRoute(
   "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/"
 )({
   component: IntegrationsListPage,
+  validateSearch: zodValidator(IntegrationsListPageQuerySchema),
   beforeLoad: ({ context }) => {
     return {
       breadcrumbs: [
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/SecretSyncDetailsByIDPage.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/SecretSyncDetailsByIDPage.tsx
new file mode 100644
index 0000000000..1a67e98a0c
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/SecretSyncDetailsByIDPage.tsx
@@ -0,0 +1,154 @@
+import { Helmet } from "react-helmet";
+import { faBan, faChevronLeft } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { useNavigate, useParams } from "@tanstack/react-router";
+
+import { ProjectPermissionCan } from "@app/components/permissions";
+import { EditSecretSyncModal } from "@app/components/secret-syncs";
+import { SecretSyncEditFields } from "@app/components/secret-syncs/types";
+import { Button, ContentLoader, EmptyState } from "@app/components/v2";
+import { ROUTE_PATHS } from "@app/const/routes";
+import { ProjectPermissionSub } from "@app/context";
+import { ProjectPermissionSecretSyncActions } from "@app/context/ProjectPermissionContext/types";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { usePopUp } from "@app/hooks";
+import { SecretSync, useGetSecretSync } from "@app/hooks/api/secretSyncs";
+import { IntegrationsListPageTabs } from "@app/types/integrations";
+
+import {
+  SecretSyncActionTriggers,
+  SecretSyncAuditLogsSection,
+  SecretSyncDestinationSection,
+  SecretSyncDetailsSection,
+  SecretSyncOptionsSection,
+  SecretSyncSourceSection
+} from "./components";
+
+const PageContent = () => {
+  const navigate = useNavigate();
+  const { destination, syncId, projectId } = useParams({
+    from: ROUTE_PATHS.SecretManager.SecretSyncDetailsByIDPage.id,
+    select: (params) => ({
+      ...params,
+      destination: params.destination as SecretSync
+    })
+  });
+
+  const { handlePopUpToggle, popUp, handlePopUpOpen } = usePopUp(["editSync"] as const);
+
+  const { data: secretSync, isPending } = useGetSecretSync(destination, syncId, {
+    refetchInterval: 4000
+  });
+
+  if (isPending) {
+    return (
+      <div className="flex h-full w-full items-center justify-center">
+        <ContentLoader />
+      </div>
+    );
+  }
+
+  if (!secretSync) {
+    return (
+      <div className="flex h-full w-full items-center justify-center px-20">
+        <EmptyState
+          className="max-w-2xl rounded-md text-center"
+          icon={faBan}
+          title={`Could not find ${SECRET_SYNC_MAP[destination].name ?? "Secret"} Sync with ID ${syncId}`}
+        />
+      </div>
+    );
+  }
+
+  const destinationDetails = SECRET_SYNC_MAP[secretSync.destination];
+
+  const handleEditDetails = () => handlePopUpOpen("editSync", SecretSyncEditFields.Details);
+
+  const handleEditSource = () => handlePopUpOpen("editSync", SecretSyncEditFields.Source);
+
+  // const handleEditOptions = () => handlePopUpOpen("editSync", SecretSyncEditFields.Options);
+
+  const handleEditDestination = () => handlePopUpOpen("editSync", SecretSyncEditFields.Destination);
+
+  return (
+    <>
+      <div className="container mx-auto flex flex-col justify-between bg-bunker-800 font-inter text-white">
+        <div className="mx-auto mb-6 w-full max-w-7xl px-6 py-6">
+          <Button
+            variant="link"
+            type="submit"
+            leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
+            onClick={() => {
+              navigate({
+                to: ROUTE_PATHS.SecretManager.IntegrationsListPage.path,
+                params: {
+                  projectId
+                },
+                search: {
+                  selectedTab: IntegrationsListPageTabs.SecretSyncs
+                }
+              });
+            }}
+            className="mb-4"
+          >
+            Secret Syncs
+          </Button>
+          <div className="mb-6 flex w-full items-center gap-3">
+            <img
+              alt={`${destinationDetails.name} sync`}
+              src={`/images/integrations/${destinationDetails.image}`}
+              className="ml-1 mt-3 w-16"
+            />
+            <div>
+              <p className="text-3xl font-semibold text-white">{secretSync.name}</p>
+              <p className="leading-3 text-bunker-300">{destinationDetails.name} Sync</p>
+            </div>
+            <SecretSyncActionTriggers secretSync={secretSync} />
+          </div>
+          <div className="flex justify-center">
+            <div className="mr-4 flex w-72 flex-col gap-4">
+              <SecretSyncDetailsSection secretSync={secretSync} onEditDetails={handleEditDetails} />
+              <SecretSyncSourceSection secretSync={secretSync} onEditSource={handleEditSource} />
+              <SecretSyncOptionsSection
+                secretSync={secretSync}
+                // onEditOptions={handleEditOptions}
+              />
+            </div>
+            <div className="flex flex-1 flex-col gap-4">
+              <SecretSyncDestinationSection
+                secretSync={secretSync}
+                onEditDestination={handleEditDestination}
+              />
+              <SecretSyncAuditLogsSection secretSync={secretSync} />
+            </div>
+          </div>
+        </div>
+      </div>
+      <EditSecretSyncModal
+        isOpen={popUp.editSync.isOpen}
+        onOpenChange={(isOpen) => handlePopUpToggle("editSync", isOpen)}
+        fields={popUp.editSync.data}
+        secretSync={secretSync}
+      />
+    </>
+  );
+};
+
+export const SecretSyncDetailsByIDPage = () => {
+  return (
+    <>
+      <Helmet>
+        <title>Secret Sync | Infisical</title>
+        <link rel="icon" href="/infisical.ico" />
+      </Helmet>
+      <ProjectPermissionCan
+        renderGuardBanner
+        passThrough={false}
+        I={ProjectPermissionSecretSyncActions.Read}
+        a={ProjectPermissionSub.SecretSyncs}
+      >
+        <PageContent />
+      </ProjectPermissionCan>
+    </>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncActionTriggers.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncActionTriggers.tsx
new file mode 100644
index 0000000000..bc4f6d2b88
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncActionTriggers.tsx
@@ -0,0 +1,312 @@
+import { useCallback } from "react";
+import {
+  faBan,
+  faCheck,
+  faCopy,
+  faDownload,
+  faEllipsisV,
+  faEraser,
+  faInfoCircle,
+  faRotate,
+  faToggleOff,
+  faToggleOn,
+  faTrash
+} from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { useNavigate } from "@tanstack/react-router";
+
+import { createNotification } from "@app/components/notifications";
+import { ProjectPermissionCan } from "@app/components/permissions";
+import {
+  DeleteSecretSyncModal,
+  SecretSyncImportSecretsModal,
+  SecretSyncImportStatusBadge,
+  SecretSyncRemoveSecretsModal,
+  SecretSyncRemoveStatusBadge
+} from "@app/components/secret-syncs";
+import {
+  Badge,
+  Button,
+  DropdownMenu,
+  DropdownMenuContent,
+  DropdownMenuItem,
+  DropdownMenuTrigger,
+  IconButton,
+  Tooltip
+} from "@app/components/v2";
+import { ROUTE_PATHS } from "@app/const/routes";
+import { ProjectPermissionSub } from "@app/context";
+import { ProjectPermissionSecretSyncActions } from "@app/context/ProjectPermissionContext/types";
+import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
+import { usePopUp, useToggle } from "@app/hooks";
+import {
+  TSecretSync,
+  useSecretSyncOption,
+  useTriggerSecretSyncSyncSecrets,
+  useUpdateSecretSync
+} from "@app/hooks/api/secretSyncs";
+import { IntegrationsListPageTabs } from "@app/types/integrations";
+
+type Props = {
+  secretSync: TSecretSync;
+};
+
+export const SecretSyncActionTriggers = ({ secretSync }: Props) => {
+  const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
+    "importSecrets",
+    "removeSecrets",
+    "deleteSync"
+  ] as const);
+
+  const navigate = useNavigate();
+
+  const triggerSyncSecrets = useTriggerSecretSyncSyncSecrets();
+  const updateSync = useUpdateSecretSync();
+
+  const { destination } = secretSync;
+
+  const destinationName = SECRET_SYNC_MAP[destination].name;
+  const { syncOption } = useSecretSyncOption(destination);
+
+  const [isIdCopied, setIsIdCopied] = useToggle(false);
+
+  const handleCopyId = useCallback(() => {
+    setIsIdCopied.on();
+    navigator.clipboard.writeText(secretSync.id);
+
+    createNotification({
+      text: "Secret Sync ID copied to clipboard",
+      type: "info"
+    });
+
+    const timer = setTimeout(() => setIsIdCopied.off(), 2000);
+
+    // eslint-disable-next-line consistent-return
+    return () => clearTimeout(timer);
+  }, [isIdCopied]);
+
+  const handleToggleEnableSync = async () => {
+    const isAutoSyncEnabled = !secretSync.isAutoSyncEnabled;
+
+    try {
+      await updateSync.mutateAsync({
+        syncId: secretSync.id,
+        destination: secretSync.destination,
+        isAutoSyncEnabled
+      });
+
+      createNotification({
+        text: `Successfully ${isAutoSyncEnabled ? "enabled" : "disabled"} auto-sync for ${destinationName} Sync`,
+        type: "success"
+      });
+    } catch {
+      createNotification({
+        text: `Failed to ${isAutoSyncEnabled ? "enable" : "disable"} auto-sync for ${destinationName} Sync`,
+        type: "error"
+      });
+    }
+  };
+
+  const handleTriggerSync = async () => {
+    try {
+      await triggerSyncSecrets.mutateAsync({
+        syncId: secretSync.id,
+        destination: secretSync.destination
+      });
+
+      createNotification({
+        text: `Successfully triggered ${destinationName} Sync`,
+        type: "success"
+      });
+    } catch {
+      createNotification({
+        text: `Failed to trigger ${destinationName} Sync`,
+        type: "error"
+      });
+    }
+  };
+
+  return (
+    <>
+      <div className="ml-auto mt-4 flex flex-wrap items-center justify-end gap-2">
+        <SecretSyncImportStatusBadge secretSync={secretSync} />
+        <SecretSyncRemoveStatusBadge secretSync={secretSync} />
+        {secretSync.isAutoSyncEnabled ? (
+          <Badge
+            variant="success"
+            className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap"
+          >
+            <FontAwesomeIcon icon={faRotate} />
+            <span>Auto-Sync Enabled</span>
+          </Badge>
+        ) : (
+          <Tooltip
+            className="text-xs"
+            content="Auto-Sync is disabled. Changes to the source location will not be automatically synced to the destination."
+          >
+            <div>
+              <Badge className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap bg-mineshaft-400/50 text-bunker-300">
+                <FontAwesomeIcon icon={faBan} />
+                <span>Auto-Sync Disabled</span>
+              </Badge>
+            </div>
+          </Tooltip>
+        )}
+        <div>
+          <ProjectPermissionCan
+            I={ProjectPermissionSecretSyncActions.SyncSecrets}
+            a={ProjectPermissionSub.SecretSyncs}
+          >
+            {(isAllowed: boolean) => (
+              <Button
+                variant="outline_bg"
+                leftIcon={<FontAwesomeIcon icon={faRotate} />}
+                onClick={handleTriggerSync}
+                className="h-9 rounded-r-none bg-mineshaft-500"
+                isDisabled={!isAllowed}
+              >
+                Trigger Sync
+              </Button>
+            )}
+          </ProjectPermissionCan>
+          <DropdownMenu>
+            <DropdownMenuTrigger asChild>
+              <IconButton
+                ariaLabel="add-folder-or-import"
+                variant="outline_bg"
+                className="h-9 w-10 rounded-l-none border-l-2 border-mineshaft border-l-mineshaft-700 bg-mineshaft-500"
+              >
+                <FontAwesomeIcon icon={faEllipsisV} />
+              </IconButton>
+            </DropdownMenuTrigger>
+            <DropdownMenuContent align="end">
+              <DropdownMenuItem
+                icon={<FontAwesomeIcon icon={isIdCopied ? faCheck : faCopy} />}
+                onClick={(e) => {
+                  e.stopPropagation();
+                  handleCopyId();
+                }}
+              >
+                Copy Sync ID
+              </DropdownMenuItem>
+              {syncOption?.canImportSecrets && (
+                <ProjectPermissionCan
+                  I={ProjectPermissionSecretSyncActions.ImportSecrets}
+                  a={ProjectPermissionSub.SecretSyncs}
+                >
+                  {(isAllowed: boolean) => (
+                    <DropdownMenuItem
+                      icon={<FontAwesomeIcon icon={faDownload} />}
+                      onClick={() => handlePopUpOpen("importSecrets")}
+                      isDisabled={!isAllowed}
+                    >
+                      <Tooltip
+                        position="left"
+                        sideOffset={42}
+                        content={`Import secrets from this ${destinationName} destination into Infisical.`}
+                      >
+                        <div className="flex h-full w-full items-center justify-between gap-1">
+                          <span>Import Secrets</span>
+                          <FontAwesomeIcon
+                            className="text-bunker-300"
+                            size="sm"
+                            icon={faInfoCircle}
+                          />
+                        </div>
+                      </Tooltip>
+                    </DropdownMenuItem>
+                  )}
+                </ProjectPermissionCan>
+              )}
+              <ProjectPermissionCan
+                I={ProjectPermissionSecretSyncActions.RemoveSecrets}
+                a={ProjectPermissionSub.SecretSyncs}
+              >
+                {(isAllowed: boolean) => (
+                  <DropdownMenuItem
+                    icon={<FontAwesomeIcon icon={faEraser} />}
+                    onClick={() => handlePopUpOpen("removeSecrets")}
+                    isDisabled={!isAllowed}
+                  >
+                    <Tooltip
+                      position="left"
+                      sideOffset={42}
+                      content={`Remove secrets synced by Infisical from this ${destinationName} destination.`}
+                    >
+                      <div className="flex h-full w-full items-center justify-between gap-1">
+                        <span>Remove Secrets</span>
+                        <FontAwesomeIcon
+                          className="text-bunker-300"
+                          size="sm"
+                          icon={faInfoCircle}
+                        />
+                      </div>
+                    </Tooltip>
+                  </DropdownMenuItem>
+                )}
+              </ProjectPermissionCan>
+              <ProjectPermissionCan
+                I={ProjectPermissionSecretSyncActions.Edit}
+                a={ProjectPermissionSub.SecretSyncs}
+              >
+                {(isAllowed: boolean) => (
+                  <DropdownMenuItem
+                    isDisabled={!isAllowed}
+                    icon={
+                      <FontAwesomeIcon
+                        icon={secretSync.isAutoSyncEnabled ? faToggleOff : faToggleOn}
+                      />
+                    }
+                    onClick={handleToggleEnableSync}
+                  >
+                    {secretSync.isAutoSyncEnabled ? "Disable" : "Enable"} Auto-Sync
+                  </DropdownMenuItem>
+                )}
+              </ProjectPermissionCan>
+              <ProjectPermissionCan
+                I={ProjectPermissionSecretSyncActions.Delete}
+                a={ProjectPermissionSub.SecretSyncs}
+              >
+                {(isAllowed: boolean) => (
+                  <DropdownMenuItem
+                    isDisabled={!isAllowed}
+                    icon={<FontAwesomeIcon icon={faTrash} />}
+                    onClick={() => handlePopUpOpen("deleteSync")}
+                  >
+                    Delete Sync
+                  </DropdownMenuItem>
+                )}
+              </ProjectPermissionCan>
+            </DropdownMenuContent>
+          </DropdownMenu>
+        </div>
+      </div>
+      <SecretSyncImportSecretsModal
+        onOpenChange={(isOpen) => handlePopUpToggle("importSecrets", isOpen)}
+        isOpen={popUp.importSecrets.isOpen}
+        secretSync={secretSync}
+      />
+      <SecretSyncRemoveSecretsModal
+        onOpenChange={(isOpen) => handlePopUpToggle("removeSecrets", isOpen)}
+        isOpen={popUp.removeSecrets.isOpen}
+        secretSync={secretSync}
+      />
+      <DeleteSecretSyncModal
+        onOpenChange={(isOpen) => handlePopUpToggle("deleteSync", isOpen)}
+        isOpen={popUp.deleteSync.isOpen}
+        secretSync={secretSync}
+        onComplete={() =>
+          navigate({
+            to: ROUTE_PATHS.SecretManager.IntegrationsListPage.path,
+            params: {
+              projectId: secretSync.projectId
+            },
+            search: {
+              selectedTab: IntegrationsListPageTabs.SecretSyncs
+            }
+          })
+        }
+      />
+    </>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncAuditLogsSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncAuditLogsSection.tsx
new file mode 100644
index 0000000000..c13b5e1322
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncAuditLogsSection.tsx
@@ -0,0 +1,85 @@
+import { faFingerprint } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Link } from "@tanstack/react-router";
+
+import { useSubscription } from "@app/context";
+import { EventType } from "@app/hooks/api/auditLogs/enums";
+import { TSecretSync } from "@app/hooks/api/secretSyncs";
+import { LogsSection } from "@app/pages/organization/AuditLogsPage/components/LogsSection";
+
+const INTEGRATION_EVENTS = [
+  EventType.SECRET_SYNC_SYNC_SECRETS,
+  EventType.SECRET_SYNC_REMOVE_SECRETS,
+  EventType.SECRET_SYNC_IMPORT_SECRETS
+];
+
+type Props = {
+  secretSync: TSecretSync;
+};
+
+export const SecretSyncAuditLogsSection = ({ secretSync }: Props) => {
+  const { subscription } = useSubscription();
+
+  const auditLogsRetentionDays = subscription?.auditLogsRetentionDays ?? 30;
+
+  return (
+    <div className="flex max-h-full w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
+      <div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
+        <h3 className="font-semibold text-mineshaft-100">Sync Logs</h3>
+        {subscription.auditLogs && (
+          <p className="text-xs text-bunker-300">
+            Displaying audit logs from the last {auditLogsRetentionDays} days
+          </p>
+        )}
+      </div>
+      {subscription.auditLogs ? (
+        <LogsSection
+          refetchInterval={4000}
+          remappedHeaders={{
+            Metadata: "Sync Status"
+          }}
+          showFilters={false}
+          presets={{
+            eventMetadata: { syncId: secretSync.id },
+            startDate: new Date(new Date().setDate(new Date().getDate() - auditLogsRetentionDays)),
+            eventType: INTEGRATION_EVENTS
+          }}
+          filterClassName="bg-mineshaft-900 static"
+        />
+      ) : (
+        <div className="flex h-full items-center justify-center rounded-lg bg-mineshaft-800 text-sm text-mineshaft-200">
+          <div className="flex flex-col items-center gap-4 py-20">
+            <FontAwesomeIcon size="2x" icon={faFingerprint} />
+            <p>
+              Please{" "}
+              {subscription && subscription.slug !== null ? (
+                <Link to="/organization/billing" target="_blank" rel="noopener noreferrer">
+                  <a
+                    className="cursor-pointer underline transition-all hover:text-white"
+                    target="_blank"
+                  >
+                    upgrade your subscription
+                  </a>
+                </Link>
+              ) : (
+                <a
+                  href="https://infisical.com/scheduledemo"
+                  target="_blank"
+                  rel="noopener noreferrer"
+                >
+                  <a
+                    className="cursor-pointer underline transition-all hover:text-white"
+                    target="_blank"
+                  >
+                    upgrade your subscription
+                  </a>
+                </a>
+              )}{" "}
+              to view sync logs.
+            </p>
+          </div>
+        </div>
+      )}
+    </div>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/AwsParameterStoreSyncDestinationSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/AwsParameterStoreSyncDestinationSection.tsx
new file mode 100644
index 0000000000..3ec11c6dd6
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/AwsParameterStoreSyncDestinationSection.tsx
@@ -0,0 +1,28 @@
+import { SecretSyncLabel } from "@app/components/secret-syncs";
+import { Badge } from "@app/components/v2";
+import { AWS_REGIONS } from "@app/helpers/appConnections";
+import { TAwsParameterStoreSync } from "@app/hooks/api/secretSyncs/types/aws-parameter-store-sync";
+
+type Props = {
+  secretSync: TAwsParameterStoreSync;
+};
+
+export const AwsParameterStoreSyncDestinationSection = ({ secretSync }: Props) => {
+  const {
+    destinationConfig: { path, region }
+  } = secretSync;
+
+  const awsRegion = AWS_REGIONS.find((r) => r.slug === region);
+
+  return (
+    <>
+      <SecretSyncLabel label="Region">
+        {awsRegion?.name}
+        <Badge className="ml-1" variant="success">
+          {awsRegion?.slug}{" "}
+        </Badge>
+      </SecretSyncLabel>
+      <SecretSyncLabel label="Path">{path}</SecretSyncLabel>
+    </>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/GitHubSyncDestinationSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/GitHubSyncDestinationSection.tsx
new file mode 100644
index 0000000000..298fd3670f
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/GitHubSyncDestinationSection.tsx
@@ -0,0 +1,75 @@
+import { ReactNode } from "react";
+import { faInfoCircle } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { SecretSyncLabel } from "@app/components/secret-syncs";
+import { GitHubSyncSelectedRepositoriesTooltipContent } from "@app/components/secret-syncs/github";
+import { Tooltip } from "@app/components/v2";
+import {
+  GitHubSyncScope,
+  GitHubSyncVisibility,
+  TGitHubSync
+} from "@app/hooks/api/secretSyncs/types/github-sync";
+
+type Props = {
+  secretSync: TGitHubSync;
+};
+
+export const GitHubSyncDestinationSection = ({ secretSync }: Props) => {
+  const { destinationConfig } = secretSync;
+
+  let Components: ReactNode;
+  switch (destinationConfig.scope) {
+    case GitHubSyncScope.Organization:
+      Components = (
+        <>
+          <SecretSyncLabel label="Organization">{destinationConfig.org}</SecretSyncLabel>
+          <SecretSyncLabel label="Visibility" className="capitalize">
+            {destinationConfig.visibility} Repositories
+          </SecretSyncLabel>
+          {destinationConfig.visibility === GitHubSyncVisibility.Selected && (
+            <SecretSyncLabel label="Selected Repositories">
+              {destinationConfig.selectedRepositoryIds?.length ?? 0} Repositories
+              <Tooltip
+                side="bottom"
+                content={<GitHubSyncSelectedRepositoriesTooltipContent secretSync={secretSync} />}
+              >
+                <FontAwesomeIcon size="xs" className="ml-1 text-bunker-300" icon={faInfoCircle} />
+              </Tooltip>
+            </SecretSyncLabel>
+          )}
+        </>
+      );
+      break;
+    case GitHubSyncScope.Repository:
+      Components = (
+        <SecretSyncLabel label="Repository">
+          {destinationConfig.owner}/{destinationConfig.repo}
+        </SecretSyncLabel>
+      );
+      break;
+    case GitHubSyncScope.RepositoryEnvironment:
+      Components = (
+        <>
+          <SecretSyncLabel label="Repository">
+            {destinationConfig.owner}/{destinationConfig.repo}
+          </SecretSyncLabel>
+          <SecretSyncLabel label="Environment">{destinationConfig.env}</SecretSyncLabel>
+        </>
+      );
+      break;
+    default:
+      throw new Error(
+        `Uhandled GitHub Sync Destination Section Scope ${secretSync.destinationConfig.scope}`
+      );
+  }
+
+  return (
+    <>
+      <SecretSyncLabel className="capitalize" label="Scope">
+        {destinationConfig.scope.replace("-", " ")}
+      </SecretSyncLabel>
+      {Components}
+    </>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx
new file mode 100644
index 0000000000..fdc87c97c2
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx
@@ -0,0 +1,64 @@
+import { ReactNode } from "react";
+import { faEdit } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { ProjectPermissionCan } from "@app/components/permissions";
+import { SecretSyncLabel } from "@app/components/secret-syncs";
+import { IconButton } from "@app/components/v2";
+import { ProjectPermissionSub } from "@app/context";
+import { ProjectPermissionSecretSyncActions } from "@app/context/ProjectPermissionContext/types";
+import { APP_CONNECTION_MAP } from "@app/helpers/appConnections";
+import { SecretSync, TSecretSync } from "@app/hooks/api/secretSyncs";
+import { AwsParameterStoreSyncDestinationSection } from "@app/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/AwsParameterStoreSyncDestinationSection";
+import { GitHubSyncDestinationSection } from "@app/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/GitHubSyncDestinationSection";
+
+type Props = {
+  secretSync: TSecretSync;
+  onEditDestination: VoidFunction;
+};
+
+export const SecretSyncDestinationSection = ({ secretSync, onEditDestination }: Props) => {
+  const { destination, connection } = secretSync;
+
+  const app = APP_CONNECTION_MAP[connection.app].name;
+
+  let DestinationComponents: ReactNode;
+  switch (secretSync.destination) {
+    case SecretSync.AWSParameterStore:
+      DestinationComponents = <AwsParameterStoreSyncDestinationSection secretSync={secretSync} />;
+      break;
+    case SecretSync.GitHub:
+      DestinationComponents = <GitHubSyncDestinationSection secretSync={secretSync} />;
+      break;
+    default:
+      throw new Error(`Unhandled Destination Section components: ${destination}`);
+  }
+
+  return (
+    <div className="flex w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
+      <div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
+        <h3 className="font-semibold text-mineshaft-100">Destination Configuration</h3>
+        <ProjectPermissionCan
+          I={ProjectPermissionSecretSyncActions.Edit}
+          a={ProjectPermissionSub.SecretSyncs}
+        >
+          {(isAllowed) => (
+            <IconButton
+              variant="plain"
+              colorSchema="secondary"
+              isDisabled={!isAllowed}
+              ariaLabel="Edit sync destination"
+              onClick={onEditDestination}
+            >
+              <FontAwesomeIcon icon={faEdit} />
+            </IconButton>
+          )}
+        </ProjectPermissionCan>
+      </div>
+      <div className="flex w-full flex-wrap gap-8">
+        <SecretSyncLabel label={`${app} Connection`}>{connection.name}</SecretSyncLabel>
+        {DestinationComponents}
+      </div>
+    </div>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/index.ts b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/index.ts
new file mode 100644
index 0000000000..e92a18aac3
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/index.ts
@@ -0,0 +1 @@
+export * from "./SecretSyncDestinatonSection";
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDetailsSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDetailsSection.tsx
new file mode 100644
index 0000000000..5491d53ab4
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDetailsSection.tsx
@@ -0,0 +1,74 @@
+import { useMemo } from "react";
+import { faEdit } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { format } from "date-fns";
+
+import { ProjectPermissionCan } from "@app/components/permissions";
+import { SecretSyncLabel } from "@app/components/secret-syncs";
+import { IconButton } from "@app/components/v2";
+import { ProjectPermissionSub } from "@app/context";
+import { ProjectPermissionSecretSyncActions } from "@app/context/ProjectPermissionContext/types";
+import { SecretSyncStatus, TSecretSync } from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  secretSync: TSecretSync;
+  onEditDetails: VoidFunction;
+};
+
+export const SecretSyncDetailsSection = ({ secretSync, onEditDetails }: Props) => {
+  const { syncStatus, lastSyncMessage, lastSyncedAt, name, description } = secretSync;
+
+  const failureMessage = useMemo(() => {
+    if (syncStatus === SecretSyncStatus.Failed) {
+      if (lastSyncMessage)
+        try {
+          return JSON.stringify(JSON.parse(lastSyncMessage), null, 2);
+        } catch {
+          return lastSyncMessage;
+        }
+
+      return "An Unknown Error Occurred.";
+    }
+    return null;
+  }, [syncStatus, lastSyncMessage]);
+
+  return (
+    <div className="flex w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
+      <div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
+        <h3 className="font-semibold text-mineshaft-100">Details</h3>
+        <ProjectPermissionCan
+          I={ProjectPermissionSecretSyncActions.Edit}
+          a={ProjectPermissionSub.SecretSyncs}
+        >
+          {(isAllowed) => (
+            <IconButton
+              variant="plain"
+              colorSchema="secondary"
+              isDisabled={!isAllowed}
+              ariaLabel="Edit sync details"
+              onClick={onEditDetails}
+            >
+              <FontAwesomeIcon icon={faEdit} />
+            </IconButton>
+          )}
+        </ProjectPermissionCan>
+      </div>
+      <div>
+        <div className="space-y-3">
+          <SecretSyncLabel label="Name">{name}</SecretSyncLabel>
+          <SecretSyncLabel label="Description">{description}</SecretSyncLabel>
+          {lastSyncedAt && (
+            <SecretSyncLabel label="Last Synced">
+              {format(new Date(lastSyncedAt), "yyyy-MM-dd, hh:mm aaa")}
+            </SecretSyncLabel>
+          )}
+          {syncStatus === SecretSyncStatus.Failed && failureMessage && (
+            <SecretSyncLabel labelClassName="text-red" label="Last Sync Error">
+              <p className="break-words rounded bg-mineshaft-600 p-2 text-xs">{failureMessage}</p>
+            </SecretSyncLabel>
+          )}
+        </div>
+      </div>
+    </div>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection.tsx
new file mode 100644
index 0000000000..0e536614f8
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection.tsx
@@ -0,0 +1,57 @@
+import { SecretSyncLabel } from "@app/components/secret-syncs";
+import { SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP } from "@app/helpers/secretSyncs";
+import { TSecretSync } from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  secretSync: TSecretSync;
+  // onEditOptions: VoidFunction;
+};
+
+export const SecretSyncOptionsSection = ({
+  secretSync
+  // onEditOptions
+}: Props) => {
+  const {
+    destination,
+    syncOptions: {
+      // appendSuffix,
+      // prependPrefix,
+      initialSyncBehavior
+    }
+  } = secretSync;
+
+  return (
+    <div>
+      <div className="flex w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
+        <div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
+          <h3 className="font-semibold text-mineshaft-100">Sync Options</h3>
+          {/* <ProjectPermissionCan
+            I={ProjectPermissionSecretSyncActions.Edit}
+            a={ProjectPermissionSub.SecretSyncs}
+          >
+            {(isAllowed) => (
+              <IconButton
+                variant="plain"
+                colorSchema="secondary"
+                isDisabled={!isAllowed}
+                ariaLabel="Edit sync options"
+                onClick={onEditOptions}
+              >
+                <FontAwesomeIcon icon={faEdit} />
+              </IconButton>
+            )}
+          </ProjectPermissionCan> */}
+        </div>
+        <div>
+          <div className="space-y-3">
+            <SecretSyncLabel label="Initial Sync Behavior">
+              {SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP[initialSyncBehavior](destination).name}
+            </SecretSyncLabel>
+            {/* <SecretSyncLabel label="Prefix">{prependPrefix}</SecretSyncLabel>
+            <SecretSyncLabel label="Suffix">{appendSuffix}</SecretSyncLabel> */}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncSourceSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncSourceSection.tsx
new file mode 100644
index 0000000000..92eff2e326
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncSourceSection.tsx
@@ -0,0 +1,65 @@
+import { faEdit, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { ProjectPermissionCan } from "@app/components/permissions";
+import { SecretSyncLabel } from "@app/components/secret-syncs";
+import { Badge, IconButton, Tooltip } from "@app/components/v2";
+import { ProjectPermissionSub } from "@app/context";
+import { ProjectPermissionSecretSyncActions } from "@app/context/ProjectPermissionContext/types";
+import { TSecretSync } from "@app/hooks/api/secretSyncs";
+
+type Props = {
+  secretSync: TSecretSync;
+  onEditSource: VoidFunction;
+};
+
+export const SecretSyncSourceSection = ({ secretSync, onEditSource }: Props) => {
+  const { folder, environment } = secretSync;
+
+  return (
+    <div>
+      <div className="flex w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
+        <div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
+          <h3 className="font-semibold text-mineshaft-100">Source</h3>
+          <div>
+            {(!folder || !environment) && (
+              <Tooltip content="The source location for this sync has been deleted. Configure a new source or remove this sync.">
+                <div className="mr-1 inline-block w-min">
+                  <Badge
+                    className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap"
+                    variant="primary"
+                  >
+                    <FontAwesomeIcon icon={faTriangleExclamation} />
+                    <span>Folder Deleted</span>
+                  </Badge>
+                </div>
+              </Tooltip>
+            )}
+            <ProjectPermissionCan
+              I={ProjectPermissionSecretSyncActions.Edit}
+              a={ProjectPermissionSub.SecretSyncs}
+            >
+              {(isAllowed) => (
+                <IconButton
+                  variant="plain"
+                  colorSchema="secondary"
+                  isDisabled={!isAllowed}
+                  ariaLabel="Edit sync source"
+                  onClick={onEditSource}
+                >
+                  <FontAwesomeIcon icon={faEdit} />
+                </IconButton>
+              )}
+            </ProjectPermissionCan>
+          </div>
+        </div>
+        <div>
+          <div className="space-y-3">
+            <SecretSyncLabel label="Environment">{environment?.name}</SecretSyncLabel>
+            <SecretSyncLabel label="Path">{folder?.path}</SecretSyncLabel>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+};
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/index.ts b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/index.ts
new file mode 100644
index 0000000000..bfef41a355
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/index.ts
@@ -0,0 +1,6 @@
+export * from "./SecretSyncActionTriggers";
+export * from "./SecretSyncAuditLogsSection";
+export * from "./SecretSyncDestinationSection";
+export * from "./SecretSyncDetailsSection";
+export * from "./SecretSyncOptionsSection";
+export * from "./SecretSyncSourceSection";
diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/route.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/route.tsx
new file mode 100644
index 0000000000..7fcade4859
--- /dev/null
+++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/route.tsx
@@ -0,0 +1,26 @@
+import { createFileRoute, linkOptions } from "@tanstack/react-router";
+
+import { SecretSyncDetailsByIDPage } from "./SecretSyncDetailsByIDPage";
+
+export const Route = createFileRoute(
+  "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/secret-syncs/$destination/$syncId"
+)({
+  component: SecretSyncDetailsByIDPage,
+  beforeLoad: ({ context, params }) => {
+    return {
+      breadcrumbs: [
+        ...context.breadcrumbs,
+        {
+          label: "Integrations",
+          link: linkOptions({
+            to: "/secret-manager/$projectId/integrations",
+            params
+          })
+        },
+        {
+          label: "Secret Sync"
+        }
+      ]
+    };
+  }
+});
diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts
index 89d4a2a0bb..3267f192c9 100644
--- a/frontend/src/routeTree.gen.ts
+++ b/frontend/src/routeTree.gen.ts
@@ -169,6 +169,7 @@ import { Route as secretManagerIntegrationsAwsSecretManagerAuthorizePageRouteImp
 import { Route as secretManagerIntegrationsAwsParameterStoreConfigurePageRouteImport } from './pages/secret-manager/integrations/AwsParameterStoreConfigurePage/route'
 import { Route as secretManagerIntegrationsAwsParameterStoreAuthorizePageRouteImport } from './pages/secret-manager/integrations/AwsParameterStoreAuthorizePage/route'
 import { Route as secretManagerIntegrationsVercelOauthCallbackPageRouteImport } from './pages/secret-manager/integrations/VercelOauthCallbackPage/route'
+import { Route as secretManagerSecretSyncDetailsByIDPageRouteImport } from './pages/secret-manager/SecretSyncDetailsByIDPage/route'
 import { Route as secretManagerIntegrationsNetlifyOauthCallbackPageRouteImport } from './pages/secret-manager/integrations/NetlifyOauthCallbackPage/route'
 import { Route as secretManagerIntegrationsHerokuOauthCallbackPageRouteImport } from './pages/secret-manager/integrations/HerokuOauthCallbackPage/route'
 import { Route as secretManagerIntegrationsGitlabOauthCallbackPageRouteImport } from './pages/secret-manager/integrations/GitlabOauthCallbackPage/route'
@@ -1463,6 +1464,14 @@ const secretManagerIntegrationsVercelOauthCallbackPageRouteRoute =
       AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdSecretManagerLayoutIntegrationsRoute,
   } as any)
 
+const secretManagerSecretSyncDetailsByIDPageRouteRoute =
+  secretManagerSecretSyncDetailsByIDPageRouteImport.update({
+    id: '/secret-syncs/$destination/$syncId',
+    path: '/secret-syncs/$destination/$syncId',
+    getParentRoute: () =>
+      AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdSecretManagerLayoutIntegrationsRoute,
+  } as any)
+
 const secretManagerIntegrationsNetlifyOauthCallbackPageRouteRoute =
   secretManagerIntegrationsNetlifyOauthCallbackPageRouteImport.update({
     id: '/netlify/oauth2/callback',
@@ -2751,6 +2760,13 @@ declare module '@tanstack/react-router' {
       preLoaderRoute: typeof secretManagerIntegrationsNetlifyOauthCallbackPageRouteImport
       parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdSecretManagerLayoutIntegrationsImport
     }
+    '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/secret-syncs/$destination/$syncId': {
+      id: '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/secret-syncs/$destination/$syncId'
+      path: '/secret-syncs/$destination/$syncId'
+      fullPath: '/secret-manager/$projectId/integrations/secret-syncs/$destination/$syncId'
+      preLoaderRoute: typeof secretManagerSecretSyncDetailsByIDPageRouteImport
+      parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdSecretManagerLayoutIntegrationsImport
+    }
     '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/vercel/oauth2/callback': {
       id: '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/vercel/oauth2/callback'
       path: '/vercel/oauth2/callback'
@@ -3020,6 +3036,7 @@ interface AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdSecretManag
   secretManagerIntegrationsGitlabOauthCallbackPageRouteRoute: typeof secretManagerIntegrationsGitlabOauthCallbackPageRouteRoute
   secretManagerIntegrationsHerokuOauthCallbackPageRouteRoute: typeof secretManagerIntegrationsHerokuOauthCallbackPageRouteRoute
   secretManagerIntegrationsNetlifyOauthCallbackPageRouteRoute: typeof secretManagerIntegrationsNetlifyOauthCallbackPageRouteRoute
+  secretManagerSecretSyncDetailsByIDPageRouteRoute: typeof secretManagerSecretSyncDetailsByIDPageRouteRoute
   secretManagerIntegrationsVercelOauthCallbackPageRouteRoute: typeof secretManagerIntegrationsVercelOauthCallbackPageRouteRoute
 }
 
@@ -3177,6 +3194,8 @@ const AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdSecretManagerLa
       secretManagerIntegrationsHerokuOauthCallbackPageRouteRoute,
     secretManagerIntegrationsNetlifyOauthCallbackPageRouteRoute:
       secretManagerIntegrationsNetlifyOauthCallbackPageRouteRoute,
+    secretManagerSecretSyncDetailsByIDPageRouteRoute:
+      secretManagerSecretSyncDetailsByIDPageRouteRoute,
     secretManagerIntegrationsVercelOauthCallbackPageRouteRoute:
       secretManagerIntegrationsVercelOauthCallbackPageRouteRoute,
   }
@@ -3629,6 +3648,7 @@ export interface FileRoutesByFullPath {
   '/secret-manager/$projectId/integrations/gitlab/oauth2/callback': typeof secretManagerIntegrationsGitlabOauthCallbackPageRouteRoute
   '/secret-manager/$projectId/integrations/heroku/oauth2/callback': typeof secretManagerIntegrationsHerokuOauthCallbackPageRouteRoute
   '/secret-manager/$projectId/integrations/netlify/oauth2/callback': typeof secretManagerIntegrationsNetlifyOauthCallbackPageRouteRoute
+  '/secret-manager/$projectId/integrations/secret-syncs/$destination/$syncId': typeof secretManagerSecretSyncDetailsByIDPageRouteRoute
   '/secret-manager/$projectId/integrations/vercel/oauth2/callback': typeof secretManagerIntegrationsVercelOauthCallbackPageRouteRoute
 }
 
@@ -3793,6 +3813,7 @@ export interface FileRoutesByTo {
   '/secret-manager/$projectId/integrations/gitlab/oauth2/callback': typeof secretManagerIntegrationsGitlabOauthCallbackPageRouteRoute
   '/secret-manager/$projectId/integrations/heroku/oauth2/callback': typeof secretManagerIntegrationsHerokuOauthCallbackPageRouteRoute
   '/secret-manager/$projectId/integrations/netlify/oauth2/callback': typeof secretManagerIntegrationsNetlifyOauthCallbackPageRouteRoute
+  '/secret-manager/$projectId/integrations/secret-syncs/$destination/$syncId': typeof secretManagerSecretSyncDetailsByIDPageRouteRoute
   '/secret-manager/$projectId/integrations/vercel/oauth2/callback': typeof secretManagerIntegrationsVercelOauthCallbackPageRouteRoute
 }
 
@@ -3972,6 +3993,7 @@ export interface FileRoutesById {
   '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/gitlab/oauth2/callback': typeof secretManagerIntegrationsGitlabOauthCallbackPageRouteRoute
   '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/heroku/oauth2/callback': typeof secretManagerIntegrationsHerokuOauthCallbackPageRouteRoute
   '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/netlify/oauth2/callback': typeof secretManagerIntegrationsNetlifyOauthCallbackPageRouteRoute
+  '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/secret-syncs/$destination/$syncId': typeof secretManagerSecretSyncDetailsByIDPageRouteRoute
   '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/vercel/oauth2/callback': typeof secretManagerIntegrationsVercelOauthCallbackPageRouteRoute
 }
 
@@ -4143,6 +4165,7 @@ export interface FileRouteTypes {
     | '/secret-manager/$projectId/integrations/gitlab/oauth2/callback'
     | '/secret-manager/$projectId/integrations/heroku/oauth2/callback'
     | '/secret-manager/$projectId/integrations/netlify/oauth2/callback'
+    | '/secret-manager/$projectId/integrations/secret-syncs/$destination/$syncId'
     | '/secret-manager/$projectId/integrations/vercel/oauth2/callback'
   fileRoutesByTo: FileRoutesByTo
   to:
@@ -4306,6 +4329,7 @@ export interface FileRouteTypes {
     | '/secret-manager/$projectId/integrations/gitlab/oauth2/callback'
     | '/secret-manager/$projectId/integrations/heroku/oauth2/callback'
     | '/secret-manager/$projectId/integrations/netlify/oauth2/callback'
+    | '/secret-manager/$projectId/integrations/secret-syncs/$destination/$syncId'
     | '/secret-manager/$projectId/integrations/vercel/oauth2/callback'
   id:
     | '__root__'
@@ -4483,6 +4507,7 @@ export interface FileRouteTypes {
     | '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/gitlab/oauth2/callback'
     | '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/heroku/oauth2/callback'
     | '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/netlify/oauth2/callback'
+    | '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/secret-syncs/$destination/$syncId'
     | '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/vercel/oauth2/callback'
   fileRoutesById: FileRoutesById
 }
@@ -5047,6 +5072,7 @@ export const routeTree = rootRoute
         "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/gitlab/oauth2/callback",
         "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/heroku/oauth2/callback",
         "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/netlify/oauth2/callback",
+        "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/secret-syncs/$destination/$syncId",
         "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/vercel/oauth2/callback"
       ]
     },
@@ -5426,6 +5452,10 @@ export const routeTree = rootRoute
       "filePath": "secret-manager/integrations/NetlifyOauthCallbackPage/route.tsx",
       "parent": "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations"
     },
+    "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/secret-syncs/$destination/$syncId": {
+      "filePath": "secret-manager/SecretSyncDetailsByIDPage/route.tsx",
+      "parent": "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations"
+    },
     "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations/vercel/oauth2/callback": {
       "filePath": "secret-manager/integrations/VercelOauthCallbackPage/route.tsx",
       "parent": "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations"
diff --git a/frontend/src/routes.ts b/frontend/src/routes.ts
index 4fc7483619..b695f0c3a7 100644
--- a/frontend/src/routes.ts
+++ b/frontend/src/routes.ts
@@ -41,6 +41,10 @@ const secretManagerRoutes = route("/secret-manager/$projectId", [
     route("/integrations", [
       index("secret-manager/IntegrationsListPage/route.tsx"),
       route("/$integrationId", "secret-manager/IntegrationsDetailsByIDPage/route.tsx"),
+      route(
+        "/secret-syncs/$destination/$syncId",
+        "secret-manager/SecretSyncDetailsByIDPage/route.tsx"
+      ),
       route(
         "/aws-parameter-store/authorize",
         "secret-manager/integrations/AwsParameterStoreAuthorizePage/route.tsx"
diff --git a/frontend/src/types/integrations.ts b/frontend/src/types/integrations.ts
new file mode 100644
index 0000000000..dfa6e38d5d
--- /dev/null
+++ b/frontend/src/types/integrations.ts
@@ -0,0 +1,6 @@
+export enum IntegrationsListPageTabs {
+  NativeIntegrations = "native-integrations",
+  FrameworkIntegrations = "framework-integrations",
+  InfrastructureIntegrations = "infrastructure-integrations",
+  SecretSyncs = "secret-syncs"
+}