import type { MountedMastraCode } from '@mastra/code-sdk'; import type { NotificationPriority } from '@mastra/core/notifications'; import type { Context } from 'hono'; import { GithubAppIdentity } from './app-identity.js'; import type { GithubIntegration, GithubRepositoryPermission } from './integration.js'; import type { GithubSignalSubscriptionRow, GithubSubscriptionStorage, GithubWebhookPullRequestTarget } from './subscriptions.js'; export interface GithubWebhookHandlerOptions { /** Integration providing webhook-secret verification + collaborator permission checks. */ github: GithubIntegration; ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise; } export interface GithubWebhookMetadata { event: string; action?: string; deliveryId: string; repository?: string; repositoryId?: number; issueNumber?: number; pullRequestNumber?: number; sender?: string; senderType?: string; installationId?: number; } export interface ParsedGithubWebhook { event: string; deliveryId: string; payload: Record; } export type GithubWebhookResult = { status: 202; body: { ok: true; ignored?: true; }; } | { status: 400; body: { error: 'bad_request'; message: string; }; } | { status: 401; body: { error: 'unauthorized'; message: string; }; }; export interface GithubWebhookNotification { action: string; kind: string; priority: NotificationPriority; summary: string; terminal: boolean; metadata: GithubWebhookMetadata & { pullRequestNumber: number; repositoryId: number; installationId: number; }; payload: Record; } /** The Factory session row fields a woken session has to run as. */ export type FactorySessionOwner = { userId: string; orgId: string; }; /** * The integration surface this dispatch uses. Narrow on purpose: the GitHub App * integration and the platform-backed one are unrelated classes, and only this * much is common to both. */ export interface GithubWebhookDispatchIntegration { /** App slug, used to recognize Factory's own bot identity. */ readonly slug?: string; /** * Resolved identity of the App this integration posts as. Preferred over * {@link slug}, which names the deployment's own self-hosted App and is unset * on deployments that run against Platform's App. */ readonly identity?: GithubAppIdentity; readonly integrationStorage: GithubSubscriptionStorage; /** * Extra bot logins this deployment authorizes to trigger author-gated * notifications, merged over `DEFAULT_AUTHORIZED_BOTS`. */ readonly authorizedBots?: readonly string[]; readonly sourceControlStorage: { sessions: { getBySessionId(sessionId: string): Promise; }; }; getRepositoryCollaboratorPermission(installationId: number, repoFullName: string, username: string, signal?: AbortSignal): Promise; } export interface GithubWebhookDispatchDependencies { controller: MountedMastraCode['controller']; /** * Integration used by the default sender-authorization check (collaborator * permission lookup) and to resolve the owner of a session being recreated. * Author-gated notifications fail closed when neither this nor an * `isAuthorizedSender` override is supplied. */ github?: GithubWebhookDispatchIntegration; listSubscriptions?: (target: GithubWebhookPullRequestTarget, options?: { includeTerminal?: boolean; }) => Promise; retireSubscription?: (id: string, status: 'open' | 'closed' | 'merged') => Promise; isAuthorizedSender?: (notification: GithubWebhookNotification) => Promise; /** Called when the sender gate drops a notification, so the drop is observable. */ onSenderRejected?: (notification: GithubWebhookNotification) => void; onTargetError?: (subscription: GithubSignalSubscriptionRow, error: unknown) => void; /** Called when a subscription names a thread this deployment does not hold. */ onTargetSkipped?: (subscription: GithubSignalSubscriptionRow) => void; } export declare function normalizeGithubWebhookMetadata(parsed: ParsedGithubWebhook): GithubWebhookMetadata; export declare function classifyGithubWebhook(parsed: ParsedGithubWebhook): GithubWebhookNotification | undefined; /** * Reviewer bots authorized out of the box. Deployments extend — never replace — * this set through the integration's `authorizedBots`. */ export declare const DEFAULT_AUTHORIZED_BOTS: readonly string[]; /** * Parse a comma-separated `MASTRACODE_GITHUB_AUTHORIZED_BOTS` value into extra * bot logins. Returns undefined when nothing usable was configured. */ export declare function parseAuthorizedBotsEnv(value: string | undefined): string[] | undefined; /** Lowercased union of the default bot logins and any the deployment opted in. */ export declare function resolveAuthorizedBots(extra?: readonly string[]): Set; /** * Recognizes Factory's own GitHub App identity. GitHub forbids an app from * reviewing a pull request it authored, so `factory-review` falls back to * posting its verdict as a comment under this login. Those comments have to * clear the author gate for the review handoff to reach the authoring agent; * the rules layer still decides which of them are worth acting on. */ export declare function isFactoryAppSender(sender: string | undefined, slug: string | undefined): boolean; export declare function dispatchGithubWebhook(parsed: ParsedGithubWebhook, dependencies: GithubWebhookDispatchDependencies): Promise<{ delivered: number; failed: number; skipped: number; ignored: boolean; }>; export declare function handleGithubWebhook(c: Context, options: GithubWebhookHandlerOptions & Partial>): Promise; //# sourceMappingURL=webhook.d.ts.map