import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { InvalidStateError, OauthExchangeFailedError, TeamAlreadyConnectedError, } from "../lib/errors.generated"; import { exchangeOauthCode, type SlackOauthAccessResult } from "../lib/slackClient"; import { parseStateToken } from "../lib/slackState"; export interface CompleteSlackWorkspaceInstallDeps { exchangeOauthCode?: ( code: string, redirectUri: string, clientId: string, clientSecret: string, ) => Promise; } export interface CompleteSlackWorkspaceInstallInput { state: string; code: string; redirectUri: string; clientId: string; clientSecret: string; /** Shared secret used to verify the state token's HMAC signature; must equal the value beginSlackWorkspaceInstall signed with. */ signingSecret: string; } export async function run( db: Transaction, input: CompleteSlackWorkspaceInstallInput, ctx: CommandContext, deps: CompleteSlackWorkspaceInstallDeps = {}, ) { const state = await parseStateToken(input.state, input.signingSecret); if (!state) { return err(new InvalidStateError(input.state)); } if (!state.userId || state.userId !== ctx.actorId) { return err(new InvalidStateError("actor-mismatch")); } if (state.redirectUri !== undefined && state.redirectUri !== input.redirectUri) { return err(new InvalidStateError("redirect-uri-mismatch")); } if (!input.code) { return err(new OauthExchangeFailedError("slack-workspace-install")); } const exchange = deps.exchangeOauthCode ?? exchangeOauthCode; let oauth: SlackOauthAccessResult; try { oauth = await exchange(input.code, input.redirectUri, input.clientId, input.clientSecret); } catch { return err(new OauthExchangeFailedError("slack-workspace-install")); } if (!oauth.ok || !oauth.access_token || !oauth.team?.id) { return err(new OauthExchangeFailedError("slack-workspace-install")); } const teamId = oauth.team.id; // Singleton connection: the tenant holds at most one SlackWorkspaceIntegration row. // An ACTIVE row bound to a different workspace must be uninstalled first. // `orderBy("createdAt")` makes the picked row deterministic (oldest wins) // if multiple rows ever exist. Residual race: two concurrent installs // against an EMPTY table both see no row and both insert — TailorDB cannot // express a constant-field unique index, so that window is not closed at // the schema level (the `teamId` unique constraint still dedupes same-team // double installs). const existing = await db .selectFrom("SlackWorkspaceIntegration") .selectAll() .orderBy("createdAt") .limit(1) .forUpdate() .executeTakeFirst(); if (existing && existing.status === "ACTIVE" && existing.teamId !== teamId) { return err(new TeamAlreadyConnectedError(teamId)); } const now = new Date(); const slackWorkspaceIntegration = existing ? await db .updateTable("SlackWorkspaceIntegration") .set({ teamId, teamName: oauth.team.name ?? existing.teamName, botUserId: oauth.bot_user_id ?? existing.botUserId, status: "ACTIVE", lastValidatedAt: now, revokedAt: null, updatedAt: now, }) .where("id", "=", existing.id) .returningAll() .executeTakeFirst() : await db .insertInto("SlackWorkspaceIntegration") .values({ teamId, teamName: oauth.team.name ?? null, botUserId: oauth.bot_user_id ?? null, status: "ACTIVE", installedAt: now, lastValidatedAt: now, revokedAt: null, createdAt: now, updatedAt: now, }) .returningAll() .executeTakeFirst(); if (!slackWorkspaceIntegration) { return err(new InvalidStateError("failed-to-persist-workspace-connection")); } return ok({ slackWorkspaceIntegration, botToken: oauth.access_token }); }