@mastra/factory 0.25.0-alpha.4 → 0.25.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/auth.js +1 -2
- package/dist/boards/define-board.js +1 -2
- package/dist/boards/index.js +1 -2
- package/dist/boards/registry.js +1 -2
- package/dist/boards/relocate.js +1 -2
- package/dist/boards/review.js +1 -2
- package/dist/boards/semantics.js +1 -2
- package/dist/boards/transition-policy.js +1 -2
- package/dist/boards/work-tool-rules.js +1 -2
- package/dist/boards/work-transition-policy.js +1 -2
- package/dist/boards/work.js +1 -2
- package/dist/default-thinking-level.d.ts +3 -0
- package/dist/default-thinking-level.d.ts.map +1 -0
- package/dist/default-thinking-level.js +5 -0
- package/dist/default-thinking-level.js.map +1 -0
- package/dist/environment/build-runner.js +1 -2
- package/dist/environment/build-schedule.js +1 -2
- package/dist/environment/build-workflow.js +1 -2
- package/dist/environment/build.js +1 -2
- package/dist/environment/heads.js +1 -2
- package/dist/factory.d.ts +4 -2
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +62 -21
- package/dist/factory.js.map +1 -1
- package/dist/feed-events.js +1 -2
- package/dist/index.js +2 -2
- package/dist/integrations/channel-thread-announcements.d.ts +8 -0
- package/dist/integrations/channel-thread-announcements.d.ts.map +1 -0
- package/dist/integrations/channel-thread-announcements.js +16 -0
- package/dist/integrations/channel-thread-announcements.js.map +1 -0
- package/dist/integrations/github/acceptance-labels.js +1 -2
- package/dist/integrations/github/app-identity.js +1 -2
- package/dist/integrations/github/commits.js +1 -2
- package/dist/integrations/github/config.js +1 -2
- package/dist/integrations/github/default-rules.js +2 -3
- package/dist/integrations/github/integration.js +3 -4
- package/dist/integrations/github/issue-reconciler.js +1 -2
- package/dist/integrations/github/pat.js +1 -2
- package/dist/integrations/github/provenance.d.ts.map +1 -1
- package/dist/integrations/github/provenance.js +2 -5
- package/dist/integrations/github/provenance.js.map +1 -1
- package/dist/integrations/github/reconcile-worker.js +1 -2
- package/dist/integrations/github/reconciliation-config.js +1 -2
- package/dist/integrations/github/routes.js +4 -5
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +14 -3
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/github/sandbox-release.js +1 -2
- package/dist/integrations/github/sandbox.js +1 -2
- package/dist/integrations/github/session-subscriptions.js +1 -2
- package/dist/integrations/github/settle-or-abort.js +1 -2
- package/dist/integrations/github/stale-reviews.js +1 -2
- package/dist/integrations/github/subscriptions.js +1 -2
- package/dist/integrations/github/token-refresh.js +1 -2
- package/dist/integrations/github/webhook.d.ts.map +1 -1
- package/dist/integrations/github/webhook.js +17 -3
- package/dist/integrations/github/webhook.js.map +1 -1
- package/dist/integrations/gitlab/agent-tools.js +1 -2
- package/dist/integrations/gitlab/api.js +1 -2
- package/dist/integrations/gitlab/default-rules.js +1 -2
- package/dist/integrations/gitlab/integration.d.ts +4 -0
- package/dist/integrations/gitlab/integration.d.ts.map +1 -1
- package/dist/integrations/gitlab/integration.js +12 -4
- package/dist/integrations/gitlab/integration.js.map +1 -1
- package/dist/integrations/gitlab/issue-reconciler.js +1 -2
- package/dist/integrations/gitlab/merge-request-reconciler.js +1 -2
- package/dist/integrations/gitlab/reconciler.js +1 -2
- package/dist/integrations/gitlab/reconciliation-config.js +1 -2
- package/dist/integrations/gitlab/routes.d.ts +6 -0
- package/dist/integrations/gitlab/routes.d.ts.map +1 -1
- package/dist/integrations/gitlab/routes.js +154 -3
- package/dist/integrations/gitlab/routes.js.map +1 -1
- package/dist/integrations/gitlab/rules.d.ts.map +1 -1
- package/dist/integrations/gitlab/rules.js +5 -3
- package/dist/integrations/gitlab/rules.js.map +1 -1
- package/dist/integrations/gitlab/session-subscriptions.js +1 -2
- package/dist/integrations/gitlab/subscriptions.js +1 -2
- package/dist/integrations/gitlab/version-control.js +1 -2
- package/dist/integrations/gitlab/webhook-dispatch.js +1 -2
- package/dist/integrations/gitlab/webhook.js +1 -2
- package/dist/integrations/incidentio/agent-tools.js +1 -2
- package/dist/integrations/incidentio/api.js +1 -2
- package/dist/integrations/incidentio/claim.js +1 -2
- package/dist/integrations/incidentio/default-rules.js +1 -2
- package/dist/integrations/incidentio/intake.js +1 -2
- package/dist/integrations/incidentio/integration.js +1 -2
- package/dist/integrations/incidentio/issue-reconciler.js +1 -2
- package/dist/integrations/incidentio/reconciliation-config.js +1 -2
- package/dist/integrations/incidentio/routes.js +1 -2
- package/dist/integrations/incidentio/rules.js +1 -2
- package/dist/integrations/issue-reconcile-worker.js +1 -2
- package/dist/integrations/issue-reconciler.js +1 -2
- package/dist/integrations/jira/adf.js +1 -2
- package/dist/integrations/jira/agent-tools.js +1 -2
- package/dist/integrations/jira/api.d.ts +1 -1
- package/dist/integrations/jira/api.d.ts.map +1 -1
- package/dist/integrations/jira/api.js +2 -3
- package/dist/integrations/jira/api.js.map +1 -1
- package/dist/integrations/jira/claim.js +1 -2
- package/dist/integrations/jira/default-rules.js +1 -2
- package/dist/integrations/jira/integration.d.ts +3 -1
- package/dist/integrations/jira/integration.d.ts.map +1 -1
- package/dist/integrations/jira/integration.js +18 -4
- package/dist/integrations/jira/integration.js.map +1 -1
- package/dist/integrations/jira/issue-reconciler.js +1 -2
- package/dist/integrations/jira/reconciliation-config.js +1 -2
- package/dist/integrations/jira/routes.js +1 -2
- package/dist/integrations/jira/rules.js +1 -2
- package/dist/integrations/linear/agent-tools.d.ts +1 -1
- package/dist/integrations/linear/agent-tools.d.ts.map +1 -1
- package/dist/integrations/linear/agent-tools.js +5 -5
- package/dist/integrations/linear/agent-tools.js.map +1 -1
- package/dist/integrations/linear/claim.js +1 -2
- package/dist/integrations/linear/default-rules.js +1 -2
- package/dist/integrations/linear/integration.d.ts +2 -0
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/integration.js +2 -2
- package/dist/integrations/linear/integration.js.map +1 -1
- package/dist/integrations/linear/issue-reconciler.js +1 -2
- package/dist/integrations/linear/reconciliation-config.js +1 -2
- package/dist/integrations/linear/routes.js +1 -2
- package/dist/integrations/linear/rules.js +1 -2
- package/dist/integrations/platform/api-client.js +1 -2
- package/dist/integrations/platform/connect/routes.js +1 -2
- package/dist/integrations/platform/github/event-worker.js +6 -2
- package/dist/integrations/platform/github/event-worker.js.map +1 -1
- package/dist/integrations/platform/github/integration.js +1 -2
- package/dist/integrations/platform/gitlab/event-worker.js +1 -2
- package/dist/integrations/platform/gitlab/integration.js +1 -2
- package/dist/integrations/platform/incidentio/integration.js +1 -2
- package/dist/integrations/platform/jira/agent-tools.js +1 -2
- package/dist/integrations/platform/jira/integration.js +1 -2
- package/dist/integrations/platform/jira/routes.js +1 -2
- package/dist/integrations/platform/linear/event-worker.js +1 -2
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.js +2 -2
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/integrations/pull-request-head.d.ts +1 -0
- package/dist/integrations/pull-request-head.d.ts.map +1 -1
- package/dist/integrations/pull-request-head.js +3 -3
- package/dist/integrations/pull-request-head.js.map +1 -1
- package/dist/integrations/reconciliation-config.js +1 -2
- package/dist/integrations/slack/channel-reply-processor.d.ts +1 -0
- package/dist/integrations/slack/channel-reply-processor.d.ts.map +1 -1
- package/dist/integrations/slack/channel-reply-processor.js +16 -6
- package/dist/integrations/slack/channel-reply-processor.js.map +1 -1
- package/dist/integrations/slack/channel-session-link-processor.d.ts +1 -0
- package/dist/integrations/slack/channel-session-link-processor.d.ts.map +1 -1
- package/dist/integrations/slack/channel-session-link-processor.js +2 -3
- package/dist/integrations/slack/channel-session-link-processor.js.map +1 -1
- package/dist/integrations/slack/connect-route.js +1 -2
- package/dist/integrations/slack/emoji-shortcodes.generated.js +1 -2
- package/dist/integrations/slack/emoji.js +1 -2
- package/dist/integrations/slack/feed-publisher.js +1 -2
- package/dist/integrations/slack/integration.d.ts +5 -0
- package/dist/integrations/slack/integration.d.ts.map +1 -1
- package/dist/integrations/slack/integration.js +13 -2
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/reply-reminder-processor.js +1 -2
- package/dist/integrations/slack/reply-tool.d.ts.map +1 -1
- package/dist/integrations/slack/reply-tool.js +4 -13
- package/dist/integrations/slack/reply-tool.js.map +1 -1
- package/dist/integrations/slack/run-error-card.d.ts +3 -0
- package/dist/integrations/slack/run-error-card.d.ts.map +1 -0
- package/dist/integrations/slack/run-error-card.js +44 -0
- package/dist/integrations/slack/run-error-card.js.map +1 -0
- package/dist/integrations/slack/share-file-tool.js +1 -2
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +7 -4
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/integrations/subscription-session.js +1 -2
- package/dist/integrations/workos/integration.js +1 -2
- package/dist/mcp/disconnect.js +1 -2
- package/dist/mcp/events.js +2 -3
- package/dist/mcp/routes.js +1 -2
- package/dist/packages/_internals/workspace/dist/index.js +1 -2
- package/dist/packages/_internals/workspace/dist/index.js.map +1 -1
- package/dist/platform-auth-host.js +1 -2
- package/dist/provider-display-name.js +1 -2
- package/dist/review-verdict.d.ts +1 -0
- package/dist/review-verdict.d.ts.map +1 -1
- package/dist/review-verdict.js +9 -3
- package/dist/review-verdict.js.map +1 -1
- package/dist/routes/attention-activity.js +1 -2
- package/dist/routes/attention-parked.js +1 -2
- package/dist/routes/attention-proposed.js +1 -2
- package/dist/routes/attention-providers.js +1 -2
- package/dist/routes/attention.js +1 -2
- package/dist/routes/automation-runs.js +1 -2
- package/dist/routes/config.d.ts +7 -0
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +29 -3
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/contracts.js +1 -2
- package/dist/routes/custom-provider-source.js +1 -2
- package/dist/routes/fs.js +1 -2
- package/dist/routes/intake.js +6 -4
- package/dist/routes/intake.js.map +1 -1
- package/dist/routes/knowledge.js +1 -2
- package/dist/routes/oauth.js +1 -2
- package/dist/routes/projects.js +1 -2
- package/dist/routes/provider-credentials.js +1 -2
- package/dist/routes/route.js +1 -2
- package/dist/routes/session-access.js +1 -2
- package/dist/routes/skills.js +1 -2
- package/dist/routes/source-control-sessions.js +5 -6
- package/dist/routes/source-control-settings.js +1 -2
- package/dist/routes/surface.js +3 -4
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/telemetry.js +1 -2
- package/dist/routes/tenant-credentials.js +1 -2
- package/dist/routes/work-items.js +2 -3
- package/dist/rules/binding-context.js +1 -2
- package/dist/rules/decision-applicability.js +1 -2
- package/dist/rules/dispatch-errors.js +1 -2
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +9 -3
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/event-rules.js +1 -2
- package/dist/rules/processor.js +1 -2
- package/dist/rules/resolve.js +1 -2
- package/dist/rules/review-source-tool.js +1 -2
- package/dist/rules/start-coordinator.js +1 -2
- package/dist/rules/terminal-cleanup.js +1 -2
- package/dist/rules/tools.js +1 -2
- package/dist/rules/transition-service.js +1 -2
- package/dist/rules/types.d.ts +4 -1
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js +1 -2
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.js +1 -2
- package/dist/run-error.d.ts +13 -0
- package/dist/run-error.d.ts.map +1 -0
- package/dist/run-error.js +81 -0
- package/dist/run-error.js.map +1 -0
- package/dist/sandbox/callback-factory-sandbox.js +1 -2
- package/dist/sandbox/git-ref.js +1 -2
- package/dist/sandbox/local-factory-sandbox.d.ts +12 -4
- package/dist/sandbox/local-factory-sandbox.d.ts.map +1 -1
- package/dist/sandbox/local-factory-sandbox.js +32 -7
- package/dist/sandbox/local-factory-sandbox.js.map +1 -1
- package/dist/sandbox/materialization.js +1 -2
- package/dist/sandbox/session-retirement.js +1 -2
- package/dist/sandbox/session-sandbox.js +1 -2
- package/dist/sandbox/workdir.js +1 -2
- package/dist/secret-encryption.js +1 -2
- package/dist/server-error.js +1 -2
- package/dist/session/credential-policy.js +1 -2
- package/dist/session/default-model-hydration.js +1 -2
- package/dist/session/environment-repositories.js +1 -2
- package/dist/session/environment-state-processor.d.ts +0 -1
- package/dist/session/environment-state-processor.d.ts.map +1 -1
- package/dist/session/environment-state-processor.js +2 -3
- package/dist/session/environment-state-processor.js.map +1 -1
- package/dist/session/factory-session.js +1 -2
- package/dist/session/filesystem-capture.js +2 -3
- package/dist/session/filesystem-capture.js.map +1 -1
- package/dist/session/first-exec-capture.js +2 -3
- package/dist/session/first-exec-capture.js.map +1 -1
- package/dist/session/first-message-capture.js +1 -2
- package/dist/session/live-sessions.js +1 -2
- package/dist/session/memory-settings-hydration.js +1 -2
- package/dist/session/org-seed.js +1 -2
- package/dist/session/reply-credential-processor.js +1 -2
- package/dist/session/resource-migration.js +1 -2
- package/dist/session/run-audit.js +1 -2
- package/dist/session/session-threads.js +1 -2
- package/dist/session/session-title.js +1 -2
- package/dist/session/shell-commands.js +1 -2
- package/dist/session/source-control-tools.js +2 -3
- package/dist/session/thinking-default.d.ts +1 -1
- package/dist/session/thinking-default.d.ts.map +1 -1
- package/dist/session/thinking-default.js +11 -13
- package/dist/session/thinking-default.js.map +1 -1
- package/dist/session/thread-session-stamp.js +1 -2
- package/dist/session/thread-title-mirror.js +1 -2
- package/dist/session/thread-title-mirror.js.map +1 -1
- package/dist/session/work-item-repository.js +1 -2
- package/dist/session-owner-signal.js +1 -2
- package/dist/skills/catalog.js +1 -2
- package/dist/skills/service.js +1 -2
- package/dist/spa-static.js +1 -2
- package/dist/state-signing.js +1 -2
- package/dist/storage/domains/audit/actions.js +1 -2
- package/dist/storage/domains/audit/actors.js +1 -2
- package/dist/storage/domains/audit/agent-audit.js +1 -2
- package/dist/storage/domains/audit/base.js +1 -2
- package/dist/storage/domains/audit/domain.js +1 -2
- package/dist/storage/domains/audit/wire.js +1 -2
- package/dist/storage/domains/channel-identity/base.js +1 -2
- package/dist/storage/domains/comments/activity.js +1 -2
- package/dist/storage/domains/comments/actor.js +1 -2
- package/dist/storage/domains/comments/base.js +1 -2
- package/dist/storage/domains/comments/domain.js +1 -2
- package/dist/storage/domains/comments/feed-context.js +1 -2
- package/dist/storage/domains/comments/parse.js +1 -2
- package/dist/storage/domains/comments/routes.js +1 -2
- package/dist/storage/domains/comments/schema.js +1 -2
- package/dist/storage/domains/comments/wire.js +1 -2
- package/dist/storage/domains/credentials/base.d.ts +4 -1
- package/dist/storage/domains/credentials/base.d.ts.map +1 -1
- package/dist/storage/domains/credentials/base.js +40 -44
- package/dist/storage/domains/credentials/base.js.map +1 -1
- package/dist/storage/domains/custom-providers/base.js +1 -2
- package/dist/storage/domains/filesystem/base.js +1 -2
- package/dist/storage/domains/intake/base.d.ts +5 -0
- package/dist/storage/domains/intake/base.d.ts.map +1 -1
- package/dist/storage/domains/intake/base.js +10 -2
- package/dist/storage/domains/intake/base.js.map +1 -1
- package/dist/storage/domains/integrations/base.js +1 -2
- package/dist/storage/domains/memory-settings/base.js +1 -2
- package/dist/storage/domains/model-defaults/base.js +1 -2
- package/dist/storage/domains/projects/base.d.ts +0 -1
- package/dist/storage/domains/projects/base.d.ts.map +1 -1
- package/dist/storage/domains/projects/base.js +5 -6
- package/dist/storage/domains/projects/base.js.map +1 -1
- package/dist/storage/domains/queue-health/base.js +1 -2
- package/dist/storage/domains/source-control/base.js +1 -2
- package/dist/storage/domains/source-control/inmemory.js +1 -2
- package/dist/storage/domains/work-items/base.js +1 -2
- package/dist/storage/domains/work-items/board-version.js +1 -2
- package/dist/storage/domains/work-items/metrics.js +1 -2
- package/dist/telemetry-types.js +1 -2
- package/dist/telemetry.js +1 -2
- package/dist/timing.js +1 -2
- package/dist/tools/annotations.js +1 -2
- package/dist/tools/approval-tools.js +1 -2
- package/dist/tools/deliver.js +2 -3
- package/dist/tools/index.js +1 -2
- package/dist/tools/messaging-tools.js +1 -2
- package/dist/tools/permissions.js +1 -2
- package/dist/tools/read-tools.js +1 -2
- package/dist/tools/reports.js +1 -2
- package/dist/tools/run-watch.d.ts +0 -2
- package/dist/tools/run-watch.d.ts.map +1 -1
- package/dist/tools/run-watch.js +4 -44
- package/dist/tools/run-watch.js.map +1 -1
- package/dist/tools/sandbox-tools.js +1 -2
- package/dist/tools/scope.js +2 -3
- package/dist/tools/session-tools.js +1 -2
- package/dist/tools/sessions-state-processor.js +1 -2
- package/dist/tools/side-sessions.js +1 -2
- package/dist/tools/work-item-tools.js +1 -2
- package/dist/work-item-branch.js +1 -2
- package/dist/work-item-branch.js.map +1 -1
- package/dist/work-items/create-work-item.js +1 -2
- package/dist/work-items/decision-actions.js +1 -2
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +1 -3
- package/dist/workspace.js.map +1 -1
- package/factory-skills/factory-gitlab-review/SKILL.md +1 -1
- package/factory-skills/factory-plan/SKILL.md +1 -1
- package/factory-skills/factory-rereview/SKILL.md +14 -3
- package/factory-skills/factory-review/SKILL.md +14 -3
- package/factory-skills/factory-self-review/SKILL.md +1 -1
- package/factory-skills/factory-triage/SKILL.md +52 -29
- package/package.json +19 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","names":[],"sources":["../../../src/integrations/gitlab/routes.ts"],"sourcesContent":["import type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { FactorySandbox } from '@mastra/core/workspace';\nimport type { Context } from 'hono';\nimport type { RouteAuth } from '../../routes/route.js';\nimport { sanitizeSegment } from '../../sandbox/workdir.js';\nimport type { AuditEmitter } from '../../storage/domains/audit/domain.js';\nimport type { IntakeStorage } from '../../storage/domains/intake/base.js';\nimport { GitLabApiError } from './api.js';\nimport {\n decodeIssueReference,\n decodeSourceId,\n encodeIssueReference,\n encodeSourceId,\n gitlabConnection,\n} from './integration.js';\nimport type { GitLabIntegrationBase } from './integration.js';\nimport { listMergeRequestSubscriptionsForThread, mergeRequestUrl } from './subscriptions.js';\nimport { handleGitLabWebhook } from './webhook.js';\nimport type { GitLabWebhookHandlerOptions, ParsedGitLabWebhook } from './webhook.js';\n\ntype RouteContext = Context;\n\nfunction loose(c: unknown): RouteContext {\n return c as RouteContext;\n}\n\nexport interface BuildGitLabRoutesOptions {\n gitlab?: GitLabIntegrationBase;\n auth?: RouteAuth;\n intake?: IntakeStorage;\n sandbox?: FactorySandbox;\n emitAudit?: AuditEmitter['emit'];\n webhookSecret?: string;\n ingestFactoryEvent?: (event: ParsedGitLabWebhook) => Promise<unknown>;\n /** Mounted agent controller; enables webhook delivery to subscribed sessions. */\n controller?: GitLabWebhookHandlerOptions['controller'];\n}\n\nasync function resolveOrgTenant(\n c: RouteContext,\n auth: RouteAuth,\n): Promise<{ tenant: { orgId: string; userId: string } } | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) return { response: c.json({ error: 'unauthorized', reason: 'auth_required' }, 401) };\n if (!tenant.orgId) {\n return {\n response: c.json(\n {\n error: 'organization_required',\n message: 'GitLab intake requires an organization. Personal accounts cannot use GitLab intake.',\n },\n 403,\n ),\n };\n }\n return { tenant: { orgId: tenant.orgId, userId: tenant.userId } };\n}\n\nfunction gitlabFetchError(c: RouteContext, error: unknown) {\n if (error instanceof GitLabApiError && error.code === 'gitlab_auth_failed') {\n return c.json({ error: 'gitlab_auth_failed', message: error.message }, 409);\n }\n return c.json({ error: 'gitlab_fetch_failed', message: error instanceof Error ? error.message : String(error) }, 502);\n}\n\ntype GitLabSourceIdentityMigration = { from: string; to: string };\n\nfunction gitlabProjectPayload(source: { id: string; name: string; metadata?: Record<string, unknown> }) {\n const connectionId = typeof source.metadata?.connectionId === 'string' ? source.metadata.connectionId : null;\n const projectId = typeof source.metadata?.projectId === 'string' ? source.metadata.projectId : null;\n const projectPath = typeof source.metadata?.projectPath === 'string' ? source.metadata.projectPath : source.name;\n if (!connectionId || !projectId) return null;\n const repositoryName = projectPath.split('/').filter(Boolean).at(-1) ?? 'repo';\n return {\n id: source.id,\n name: source.name,\n projectId,\n projectPath,\n connectionId,\n accountLabel: typeof source.metadata?.accountLabel === 'string' ? source.metadata.accountLabel : null,\n defaultBranch: typeof source.metadata?.defaultBranch === 'string' ? source.metadata.defaultBranch : 'main',\n sandboxProvider: 'none',\n sandboxWorkdir: `~/${sanitizeSegment(repositoryName)}`,\n };\n}\n\nfunction positiveId(value: string | undefined): number | null {\n const number = Number(value);\n return value && /^[1-9]\\d*$/.test(value) && Number.isSafeInteger(number) ? number : null;\n}\n\nfunction mergeRequestSourceKey(host: string, projectId: number, mergeRequestIid: number): string {\n return `gitlab-pr:${Buffer.from(JSON.stringify({ version: 1, host, projectId, mergeRequestIid }), 'utf8').toString('base64url')}`;\n}\n\nasync function reconcileGitLabSourceIdentity({\n intake,\n orgId,\n sources,\n}: {\n intake: IntakeStorage;\n orgId: string;\n sources: Array<{ id: string; metadata?: Record<string, unknown> }>;\n}): Promise<{ migrations: GitLabSourceIdentityMigration[]; conflicts: GitLabSourceIdentityMigration[] }> {\n await intake.ensureReady();\n const [config, bindings] = await Promise.all([\n intake.getConfig({ orgId }),\n intake.listBindings({ orgId, integrationId: 'gitlab' }),\n ]);\n const selected = config.gitlab?.sourceIds ?? [];\n const canonicalByProject = new Map<string, string[]>();\n for (const source of sources) {\n const reference = decodeSourceId(source.id);\n if (!reference?.host) continue;\n const ids = canonicalByProject.get(reference.projectId) ?? [];\n ids.push(source.id);\n canonicalByProject.set(reference.projectId, ids);\n }\n\n const migrations = new Map<string, string>();\n for (const sourceId of new Set([...selected, ...bindings.map(binding => binding.sourceId)])) {\n const reference = decodeSourceId(sourceId);\n if (!reference || reference.host) continue;\n const candidates = canonicalByProject.get(reference.projectId) ?? [];\n if (candidates.length === 1) migrations.set(sourceId, candidates[0]!);\n }\n return intake.migrateSourceIds({\n orgId,\n integrationId: 'gitlab',\n migrations: [...migrations].map(([from, to]) => ({ from, to })),\n });\n}\n\nexport function buildGitLabRoutes(options: BuildGitLabRoutesOptions): ApiRoute[] {\n const routes: ApiRoute[] = [];\n const { gitlab, auth, intake, emitAudit } = options;\n const enabled = Boolean(gitlab && auth?.enabled());\n\n if (gitlab && auth) {\n routes.push(\n registerApiRoute('/web/gitlab/status', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const diagnostics = gitlab.diagnostics();\n if (!enabled) {\n return c.json({ enabled: false, configured: true, reauthRequired: false, reason: 'missing_config' });\n }\n await auth.ensureUser(loose(c));\n const tenant = auth.tenant(loose(c));\n if (!tenant) return c.json({ error: 'unauthorized', reason: 'auth_required' }, 401);\n if (!tenant.orgId) {\n return c.json({\n enabled: true,\n configured: false,\n organizationRequired: true,\n connections: [],\n accounts: [],\n reauthRequired: false,\n reason: 'organization_required',\n });\n }\n\n try {\n await gitlab.verifyStatus();\n const connections = await gitlab.statusConnections();\n const active = connections?.filter(connection => connection.status === 'active');\n const direct = connections === undefined;\n const endpointHost = typeof diagnostics.endpointHost === 'string' ? diagnostics.endpointHost : null;\n const accounts = direct\n ? endpointHost\n ? [endpointHost]\n : []\n : (active ?? []).flatMap(connection => (connection.accountLabel ? [connection.accountLabel] : []));\n const configured = direct || (active?.length ?? 0) > 0;\n return c.json({\n enabled: true,\n configured,\n mode: direct ? 'direct' : 'platform',\n ...(connections ? { connections } : {}),\n accounts,\n reauthRequired: connections?.some(connection => connection.status === 'needs_reauth') ?? false,\n reason: configured ? 'ready' : 'not_connected',\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n registerApiRoute('/web/gitlab/projects', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n try {\n const sources = await gitlab.intake.listSources(resolved.tenant);\n if (intake) {\n const identity = await reconcileGitLabSourceIdentity({\n intake,\n orgId: resolved.tenant.orgId,\n sources,\n });\n if (identity.conflicts.length > 0) {\n return c.json(\n {\n error: 'gitlab_source_identity_conflict',\n message: 'Conflicting routes exist for the same GitLab project. Resolve the duplicate bindings.',\n conflicts: identity.conflicts,\n },\n 409,\n );\n }\n if (identity.migrations.length > 0) {\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.intake.config_updated',\n targets: identity.migrations.map(migration => ({ type: 'intake_source', id: migration.to })),\n metadata: { provider: 'gitlab', migrated: identity.migrations.length },\n },\n });\n }\n }\n return c.json({\n projects: sources.flatMap(source => {\n const project = gitlabProjectPayload(source);\n return project ? [{ ...project, sandboxProvider: options.sandbox ? 'custom' : 'none' }] : [];\n }),\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n registerApiRoute('/web/gitlab/projects/registration', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const input = (await c.req.json().catch(() => null)) as { sourceId?: unknown } | null;\n const sourceId = typeof input?.sourceId === 'string' ? input.sourceId.trim() : '';\n if (!sourceId) return c.json({ error: 'invalid_gitlab_source' }, 400);\n try {\n const source = (await gitlab.intake.listSources(resolved.tenant)).find(\n candidate => candidate.id === sourceId,\n );\n const project = source ? gitlabProjectPayload(source) : null;\n if (!project) return c.json({ error: 'gitlab_project_not_found' }, 404);\n const installation = await gitlab.versionControl.registerInstallation({\n orgId: resolved.tenant.orgId,\n userId: resolved.tenant.userId,\n installation: {\n externalId: project.connectionId,\n accountName: project.accountLabel ?? 'GitLab',\n accountType: 'GitLab',\n metadata: { connection: gitlabConnection(project.connectionId) },\n },\n });\n return c.json({\n project: {\n ...project,\n installationStorageId: installation.id,\n sandboxProvider: options.sandbox ? 'custom' : 'none',\n },\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n registerApiRoute('/web/gitlab/projects/:id/prs', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const factoryProjectId = c.req.query('factoryProjectId')?.trim();\n const page = positiveId(c.req.query('page') ?? '1');\n if (!factoryProjectId || !page) return c.json({ error: 'invalid_request' }, 400);\n if ((await gitlab.resolveOrgId(factoryProjectId)) !== resolved.tenant.orgId)\n return c.json({ error: 'factory_project_not_found' }, 404);\n const linked = await gitlab.getLinkedRepository({\n orgId: resolved.tenant.orgId,\n factoryProjectId,\n projectRepositoryId: c.req.param('id'),\n });\n if (!linked) return c.json({ error: 'project_repository_not_found' }, 404);\n const projectId = positiveId(linked.repository.externalId);\n if (!projectId) return c.json({ error: 'invalid_gitlab_project' }, 502);\n try {\n const target = await gitlab.versionControl.getRepositoryTarget({\n orgId: resolved.tenant.orgId,\n repositoryId: linked.repository.id,\n });\n const result = await gitlab.versionControl.listPullRequests({\n ...target,\n includeDrafts: false,\n cursor: String(page),\n });\n return c.json({\n pullRequests: result.pullRequests.map(pr => ({\n number: Number(pr.id),\n externalId: mergeRequestSourceKey(linked.host, projectId, Number(pr.id)),\n title: pr.title,\n url: pr.url,\n author: pr.author,\n assignees: pr.assignees ?? [],\n requestedReviewers: pr.requestedReviewers ?? [],\n labels: pr.labels ?? [],\n baseBranch: pr.baseBranch,\n headBranch: pr.headBranch,\n createdAt: pr.createdAt,\n updatedAt: pr.updatedAt,\n })),\n nextPage: result.nextCursor === null ? null : Number(result.nextCursor),\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n registerApiRoute('/web/gitlab/projects/:id/prs/:number', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const factoryProjectId = c.req.query('factoryProjectId')?.trim();\n const number = positiveId(c.req.param('number'));\n if (!factoryProjectId || !number) return c.json({ error: 'invalid_request' }, 400);\n if ((await gitlab.resolveOrgId(factoryProjectId)) !== resolved.tenant.orgId)\n return c.json({ error: 'factory_project_not_found' }, 404);\n const linked = await gitlab.getLinkedRepository({\n orgId: resolved.tenant.orgId,\n factoryProjectId,\n projectRepositoryId: c.req.param('id'),\n });\n if (!linked) return c.json({ error: 'project_repository_not_found' }, 404);\n try {\n const target = await gitlab.versionControl.getRepositoryTarget({\n orgId: resolved.tenant.orgId,\n repositoryId: linked.repository.id,\n });\n const pr = await gitlab.versionControl.getPullRequest({ ...target, pullRequestId: String(number) });\n if (!pr) return c.json({ error: 'merge_request_not_found' }, 404);\n return c.json({\n number,\n title: pr.title,\n url: pr.url,\n author: pr.author,\n assignees: pr.assignees ?? [],\n requestedReviewers: pr.requestedReviewers ?? [],\n baseBranch: pr.baseBranch,\n headBranch: pr.headBranch,\n createdAt: pr.createdAt,\n updatedAt: pr.updatedAt,\n description: pr.body,\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n );\n }\n\n if (gitlab && auth && intake) {\n routes.push(\n registerApiRoute('/web/gitlab/issues', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const factoryProjectId = c.req.query('factoryProjectId')?.trim();\n if (!factoryProjectId) return c.json({ error: 'invalid_factory_project_id' }, 400);\n const board = c.req.query('board')?.trim();\n if (!board) return c.json({ error: 'invalid_board' }, 400);\n if ((await gitlab.resolveOrgId(factoryProjectId)) !== resolved.tenant.orgId) {\n return c.json({ error: 'factory_project_not_found' }, 404);\n }\n\n await intake.ensureReady();\n const config = await intake.getConfig({ orgId: resolved.tenant.orgId, integrationIds: ['gitlab'] });\n const selection = config.gitlab!;\n if (!selection.enabled) {\n return c.json(\n { error: 'gitlab_intake_disabled', message: 'GitLab intake is turned off in Settings.' },\n 404,\n );\n }\n const selected = new Set(selection.sourceIds ?? []);\n const sourceIds = [\n ...new Set(\n (await intake.listBindings({ orgId: resolved.tenant.orgId, integrationId: 'gitlab' }))\n .filter(\n binding =>\n binding.factoryProjectId === factoryProjectId &&\n binding.board === board &&\n selected.has(binding.sourceId),\n )\n .map(binding => binding.sourceId),\n ),\n ];\n if (sourceIds.length === 0) return c.json({ issues: [], nextCursor: null });\n\n try {\n const result = await gitlab.intake.listIssues({\n connection: { type: 'oauth', accessToken: 'gitlab-route' },\n sourceIds,\n cursor: c.req.query('after')?.trim() || undefined,\n });\n return c.json({\n ...result,\n issues: result.issues.map(issue => {\n const source = decodeSourceId(issue.sourceId ?? '');\n const issueIid = Number(issue.id);\n if (!source || !Number.isSafeInteger(issueIid) || issueIid <= 0) {\n throw new Error('GitLab returned an invalid routed issue reference.');\n }\n return { ...issue, externalId: encodeIssueReference({ ...source, issueIid }) };\n }),\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n );\n\n routes.push(\n registerApiRoute('/web/gitlab/issues/:issueId', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const factoryProjectId = c.req.query('factoryProjectId')?.trim();\n if (!factoryProjectId) return c.json({ error: 'invalid_factory_project_id' }, 400);\n if ((await gitlab.resolveOrgId(factoryProjectId)) !== resolved.tenant.orgId) {\n return c.json({ error: 'factory_project_not_found' }, 404);\n }\n const issueId = c.req.param('issueId')?.trim();\n const issueReference = issueId ? decodeIssueReference(issueId) : null;\n if (!issueReference) return c.json({ error: 'invalid_gitlab_issue_id' }, 400);\n\n const { host, connectionId, projectId, projectPath } = issueReference;\n const sourceId = host\n ? encodeSourceId({ host, projectId })\n : encodeSourceId({ connectionId, projectId, projectPath });\n await intake.ensureReady();\n const config = await intake.getConfig({ orgId: resolved.tenant.orgId, integrationIds: ['gitlab'] });\n const selection = config.gitlab!;\n const selected = new Set(selection.sourceIds ?? []);\n const routed =\n selection.enabled &&\n selected.has(sourceId) &&\n (await intake.listBindings({ orgId: resolved.tenant.orgId, integrationId: 'gitlab' })).some(\n binding => binding.factoryProjectId === factoryProjectId && binding.sourceId === sourceId,\n );\n if (!routed) return c.json({ error: 'gitlab_issue_not_routed' }, 404);\n\n try {\n const issue = await gitlab.intake.getIssue({\n connection: { type: 'oauth', accessToken: 'gitlab-route' },\n issueId,\n });\n if (!issue) return c.json({ error: 'gitlab_issue_not_found' }, 404);\n return c.json(issue);\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n );\n }\n\n if (gitlab && auth) {\n routes.push(\n registerApiRoute('/web/gitlab/subscriptions', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n await auth.ensureUser(loose(c));\n const tenant = auth.tenant(loose(c));\n if (!tenant?.orgId) return c.json({ error: 'unauthorized' }, 401);\n\n // Sessions read by session id; resourceId is the older address.\n const sessionId = c.req.query('sessionId');\n const resourceId = c.req.query('resourceId');\n const threadId = c.req.query('threadId');\n const target = !threadId\n ? null\n : sessionId\n ? { orgId: tenant.orgId, sessionId, threadId }\n : resourceId\n ? { orgId: tenant.orgId, resourceId, threadId }\n : null;\n if (!target) return c.json({ error: 'sessionId (or resourceId) and threadId are required' }, 400);\n\n const subscriptions = await listMergeRequestSubscriptionsForThread(target, gitlab.integrationStorage);\n return c.json({\n subscriptions: subscriptions.map(subscription => ({\n id: subscription.id,\n repoFullName: subscription.data.projectPath,\n pullRequestNumber: Number(subscription.data.changeRequestId),\n status: subscription.status,\n url: mergeRequestUrl(\n subscription.data.host,\n subscription.data.projectPath,\n subscription.data.changeRequestId,\n ),\n })),\n });\n },\n }),\n );\n }\n\n routes.push(\n registerApiRoute('/web/gitlab/webhook', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const result = await handleGitLabWebhook(loose(c), {\n webhookSecret: options.webhookSecret,\n ingestFactoryEvent: options.ingestFactoryEvent,\n ...(options.controller && gitlab\n ? {\n controller: options.controller,\n gitlab,\n onTargetError: (subscription, error) => {\n console.warn(\n `[GitLab Webhook] Delivery failed for subscription ${subscription.id} (${subscription.resourceId}/${subscription.threadId}).`,\n error,\n );\n },\n }\n : {}),\n });\n return c.json(result.body, result.status);\n },\n }),\n );\n return routes;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"routes.js","names":[],"sources":["../../../src/integrations/gitlab/routes.ts"],"sourcesContent":["import type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { FactorySandbox } from '@mastra/core/workspace';\nimport type { Context } from 'hono';\nimport type { IntakeIssue } from '../../capabilities/intake.js';\nimport type { PullRequest } from '../../capabilities/version-control.js';\nimport type { RouteAuth } from '../../routes/route.js';\nimport { sanitizeSegment } from '../../sandbox/workdir.js';\nimport type { AuditEmitter } from '../../storage/domains/audit/domain.js';\nimport type { IntakeStorage } from '../../storage/domains/intake/base.js';\nimport { GitLabApiError } from './api.js';\nimport {\n decodeIssueReference,\n decodeSourceId,\n encodeIssueReference,\n encodeSourceId,\n gitlabConnection,\n} from './integration.js';\nimport type { GitLabIntegrationBase } from './integration.js';\nimport { listMergeRequestSubscriptionsForThread, mergeRequestUrl } from './subscriptions.js';\nimport { handleGitLabWebhook } from './webhook.js';\nimport type { GitLabWebhookHandlerOptions, ParsedGitLabWebhook } from './webhook.js';\n\ntype RouteContext = Context;\n\nfunction loose(c: unknown): RouteContext {\n return c as RouteContext;\n}\n\nexport interface BuildGitLabRoutesOptions {\n gitlab?: GitLabIntegrationBase;\n auth?: RouteAuth;\n intake?: IntakeStorage;\n sandbox?: FactorySandbox;\n emitAudit?: AuditEmitter['emit'];\n webhookSecret?: string;\n ingestFactoryEvent?: (event: ParsedGitLabWebhook) => Promise<unknown>;\n /** Mounted agent controller; enables webhook delivery to subscribed sessions. */\n controller?: GitLabWebhookHandlerOptions['controller'];\n}\n\nasync function resolveOrgTenant(\n c: RouteContext,\n auth: RouteAuth,\n): Promise<{ tenant: { orgId: string; userId: string } } | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) return { response: c.json({ error: 'unauthorized', reason: 'auth_required' }, 401) };\n if (!tenant.orgId) {\n return {\n response: c.json(\n {\n error: 'organization_required',\n message: 'GitLab intake requires an organization. Personal accounts cannot use GitLab intake.',\n },\n 403,\n ),\n };\n }\n return { tenant: { orgId: tenant.orgId, userId: tenant.userId } };\n}\n\nfunction gitlabFetchError(c: RouteContext, error: unknown) {\n if (error instanceof GitLabApiError && error.code === 'gitlab_auth_failed') {\n return c.json({ error: 'gitlab_auth_failed', message: error.message }, 409);\n }\n return c.json({ error: 'gitlab_fetch_failed', message: error instanceof Error ? error.message : String(error) }, 502);\n}\n\ntype GitLabSourceIdentityMigration = { from: string; to: string };\n\nfunction gitlabProjectPayload(source: { id: string; name: string; metadata?: Record<string, unknown> }) {\n const connectionId = typeof source.metadata?.connectionId === 'string' ? source.metadata.connectionId : null;\n const projectId = typeof source.metadata?.projectId === 'string' ? source.metadata.projectId : null;\n const projectPath = typeof source.metadata?.projectPath === 'string' ? source.metadata.projectPath : source.name;\n if (!connectionId || !projectId) return null;\n const repositoryName = projectPath.split('/').filter(Boolean).at(-1) ?? 'repo';\n return {\n id: source.id,\n name: source.name,\n projectId,\n projectPath,\n connectionId,\n accountLabel: typeof source.metadata?.accountLabel === 'string' ? source.metadata.accountLabel : null,\n defaultBranch: typeof source.metadata?.defaultBranch === 'string' ? source.metadata.defaultBranch : 'main',\n sandboxProvider: 'none',\n sandboxWorkdir: `~/${sanitizeSegment(repositoryName)}`,\n };\n}\n\nfunction positiveId(value: string | undefined): number | null {\n const number = Number(value);\n return value && /^[1-9]\\d*$/.test(value) && Number.isSafeInteger(number) ? number : null;\n}\n\nfunction mergeRequestSourceKey(host: string, projectId: number, mergeRequestIid: number): string {\n return `gitlab-pr:${Buffer.from(JSON.stringify({ version: 1, host, projectId, mergeRequestIid }), 'utf8').toString('base64url')}`;\n}\n\nconst LINKED_BACKLOG_MAX_PAGES = 5;\nconst POLLED_ACTOR = '__factory_poll__';\n\nfunction listedMergeRequestEvent(\n project: { host: string; projectId: number; projectPath: string },\n pr: PullRequest,\n): ParsedGitLabWebhook {\n const iid = Number(pr.id);\n return {\n event: 'Merge Request Hook',\n deliveryId: `poll:merge-request:${project.host}:${project.projectId}:${iid}:${pr.createdAt}`,\n instanceHost: project.host,\n payload: {\n user_username: POLLED_ACTOR,\n project: { id: project.projectId, path_with_namespace: project.projectPath, web_url: `https://${project.host}/${project.projectPath}` },\n object_attributes: {\n iid,\n action: 'open',\n state: 'opened',\n title: pr.title,\n url: pr.url,\n created_at: pr.createdAt,\n updated_at: pr.updatedAt,\n source_branch: pr.headBranch,\n target_branch: pr.baseBranch,\n draft: pr.draft,\n author: pr.author ? { username: pr.author } : undefined,\n assignees: (pr.assignees ?? []).map(username => ({ username })),\n reviewers: (pr.requestedReviewers ?? []).map(username => ({ username })),\n labels: pr.labels ?? [],\n },\n },\n };\n}\n\nfunction listedMergeRequestEvents(\n project: { host: string; projectId: number; projectPath: string },\n pr: PullRequest,\n): ParsedGitLabWebhook[] {\n const opened = listedMergeRequestEvent(project, pr);\n if (!pr.headSha || pr.updatedAt === pr.createdAt) return [opened];\n return [\n opened,\n {\n ...opened,\n deliveryId: `poll:merge-request-head:${project.host}:${project.projectId}:${pr.id}:${pr.updatedAt}:${pr.headSha}`,\n payload: {\n ...opened.payload,\n object_attributes: {\n ...(opened.payload.object_attributes as Record<string, unknown>),\n action: 'update',\n last_commit: { id: pr.headSha },\n },\n },\n },\n ];\n}\n\nfunction listedIssueEvent(issue: IntakeIssue): ParsedGitLabWebhook | null {\n const source = decodeSourceId(issue.sourceId ?? '');\n const projectId = source && positiveId(source.projectId);\n const iid = positiveId(issue.id);\n const projectPath = issue.source || source?.projectPath;\n if (!source?.host || !projectId || !iid || !projectPath) return null;\n return {\n event: 'Issue Hook',\n deliveryId: `poll:issue:${source.host}:${projectId}:${iid}:${issue.createdAt}`,\n instanceHost: source.host,\n payload: {\n user_username: POLLED_ACTOR,\n project: { id: projectId, path_with_namespace: projectPath, web_url: `https://${source.host}/${projectPath}` },\n object_attributes: {\n iid,\n action: 'open',\n state: 'opened',\n title: issue.title,\n url: issue.url,\n created_at: issue.createdAt,\n updated_at: issue.updatedAt,\n author: issue.authorUsername ? { username: issue.authorUsername } : undefined,\n labels: issue.labels ?? [],\n },\n },\n };\n}\n\nasync function ingestListedEvents(events: Array<ParsedGitLabWebhook | null>, ingest?: BuildGitLabRoutesOptions['ingestFactoryEvent']) {\n if (!ingest) return;\n const listed = events.filter((event): event is ParsedGitLabWebhook => event !== null);\n const openings = listed.filter(event => !event.deliveryId.startsWith('poll:merge-request-head:'));\n const headUpdates = listed.filter(event => event.deliveryId.startsWith('poll:merge-request-head:'));\n for (const batch of [openings, headUpdates]) {\n const results = await Promise.allSettled(batch.map(event => ingest(event)));\n const rejected = results.find((result): result is PromiseRejectedResult => result.status === 'rejected');\n if (rejected) console.warn('[Mastra Factory] Failed to ingest listed GitLab events', { error: rejected.reason });\n }\n}\n\nexport async function ingestLinkedGitLabRepositoryBacklog(args: {\n gitlab: GitLabIntegrationBase;\n orgId: string;\n projectRepositoryId: string;\n ingestFactoryEvent?: BuildGitLabRoutesOptions['ingestFactoryEvent'];\n}): Promise<void> {\n if (!args.ingestFactoryEvent) return;\n const storage = args.gitlab.sourceControlStorage;\n const link = await storage?.projectRepositories.get({ orgId: args.orgId, id: args.projectRepositoryId });\n if (!link) return;\n const connection = await storage!.connections.get({ orgId: args.orgId, id: link.connectionId });\n if (!connection || connection.integrationId !== 'gitlab') return;\n const linked = await args.gitlab.getLinkedRepository({\n orgId: args.orgId,\n factoryProjectId: connection.factoryProjectId,\n projectRepositoryId: link.id,\n });\n if (!linked) return;\n const projectId = positiveId(linked.repository.externalId);\n if (!projectId) return;\n const project = { host: linked.host, projectId, projectPath: linked.repository.slug };\n const target = await args.gitlab.versionControl.getRepositoryTarget({\n orgId: args.orgId,\n repositoryId: linked.repository.id,\n });\n for (let page = 1; page <= LINKED_BACKLOG_MAX_PAGES; page += 1) {\n const result = await args.gitlab.versionControl.listPullRequests({ ...target, includeDrafts: false, cursor: String(page) });\n await ingestListedEvents(result.pullRequests.flatMap(pr => listedMergeRequestEvents(project, pr)), args.ingestFactoryEvent);\n if (result.nextCursor === null) break;\n }\n const sourceId = encodeSourceId({ host: linked.host, projectId: String(projectId) });\n let cursor: string | undefined;\n for (let page = 1; page <= LINKED_BACKLOG_MAX_PAGES; page += 1) {\n const result = await args.gitlab.intake.listIssues({ connection: target.connection, sourceIds: [sourceId], cursor });\n await ingestListedEvents(result.issues.map(listedIssueEvent), args.ingestFactoryEvent);\n if (result.nextCursor === null) break;\n cursor = result.nextCursor;\n }\n}\n\nasync function reconcileGitLabSourceIdentity({\n intake,\n orgId,\n sources,\n}: {\n intake: IntakeStorage;\n orgId: string;\n sources: Array<{ id: string; metadata?: Record<string, unknown> }>;\n}): Promise<{ migrations: GitLabSourceIdentityMigration[]; conflicts: GitLabSourceIdentityMigration[] }> {\n await intake.ensureReady();\n const [config, bindings] = await Promise.all([\n intake.getConfig({ orgId }),\n intake.listBindings({ orgId, integrationId: 'gitlab' }),\n ]);\n const selected = config.gitlab?.sourceIds ?? [];\n const canonicalByProject = new Map<string, string[]>();\n for (const source of sources) {\n const reference = decodeSourceId(source.id);\n if (!reference?.host) continue;\n const ids = canonicalByProject.get(reference.projectId) ?? [];\n ids.push(source.id);\n canonicalByProject.set(reference.projectId, ids);\n }\n\n const migrations = new Map<string, string>();\n for (const sourceId of new Set([...selected, ...bindings.map(binding => binding.sourceId)])) {\n const reference = decodeSourceId(sourceId);\n if (!reference || reference.host) continue;\n const candidates = canonicalByProject.get(reference.projectId) ?? [];\n if (candidates.length === 1) migrations.set(sourceId, candidates[0]!);\n }\n return intake.migrateSourceIds({\n orgId,\n integrationId: 'gitlab',\n migrations: [...migrations].map(([from, to]) => ({ from, to })),\n });\n}\n\nexport function buildGitLabRoutes(options: BuildGitLabRoutesOptions): ApiRoute[] {\n const routes: ApiRoute[] = [];\n const { gitlab, auth, intake, emitAudit } = options;\n const enabled = Boolean(gitlab && auth?.enabled());\n\n if (gitlab && auth) {\n routes.push(\n registerApiRoute('/web/gitlab/status', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const diagnostics = gitlab.diagnostics();\n if (!enabled) {\n return c.json({ enabled: false, configured: true, reauthRequired: false, reason: 'missing_config' });\n }\n await auth.ensureUser(loose(c));\n const tenant = auth.tenant(loose(c));\n if (!tenant) return c.json({ error: 'unauthorized', reason: 'auth_required' }, 401);\n if (!tenant.orgId) {\n return c.json({\n enabled: true,\n configured: false,\n organizationRequired: true,\n connections: [],\n accounts: [],\n reauthRequired: false,\n reason: 'organization_required',\n });\n }\n\n try {\n await gitlab.verifyStatus();\n const connections = await gitlab.statusConnections();\n const active = connections?.filter(connection => connection.status === 'active');\n const direct = connections === undefined;\n const endpointHost = typeof diagnostics.endpointHost === 'string' ? diagnostics.endpointHost : null;\n const accounts = direct\n ? endpointHost\n ? [endpointHost]\n : []\n : (active ?? []).flatMap(connection => (connection.accountLabel ? [connection.accountLabel] : []));\n const configured = direct || (active?.length ?? 0) > 0;\n return c.json({\n enabled: true,\n configured,\n mode: direct ? 'direct' : 'platform',\n ...(connections ? { connections } : {}),\n accounts,\n reauthRequired: connections?.some(connection => connection.status === 'needs_reauth') ?? false,\n reason: configured ? 'ready' : 'not_connected',\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n registerApiRoute('/web/gitlab/projects', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n try {\n const sources = await gitlab.intake.listSources(resolved.tenant);\n if (intake) {\n const identity = await reconcileGitLabSourceIdentity({\n intake,\n orgId: resolved.tenant.orgId,\n sources,\n });\n if (identity.conflicts.length > 0) {\n return c.json(\n {\n error: 'gitlab_source_identity_conflict',\n message: 'Conflicting routes exist for the same GitLab project. Resolve the duplicate bindings.',\n conflicts: identity.conflicts,\n },\n 409,\n );\n }\n if (identity.migrations.length > 0) {\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.intake.config_updated',\n targets: identity.migrations.map(migration => ({ type: 'intake_source', id: migration.to })),\n metadata: { provider: 'gitlab', migrated: identity.migrations.length },\n },\n });\n }\n }\n return c.json({\n projects: sources.flatMap(source => {\n const project = gitlabProjectPayload(source);\n return project ? [{ ...project, sandboxProvider: options.sandbox ? 'custom' : 'none' }] : [];\n }),\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n registerApiRoute('/web/gitlab/projects/registration', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const input = (await c.req.json().catch(() => null)) as { sourceId?: unknown } | null;\n const sourceId = typeof input?.sourceId === 'string' ? input.sourceId.trim() : '';\n if (!sourceId) return c.json({ error: 'invalid_gitlab_source' }, 400);\n try {\n const source = (await gitlab.intake.listSources(resolved.tenant)).find(\n candidate => candidate.id === sourceId,\n );\n const project = source ? gitlabProjectPayload(source) : null;\n if (!project) return c.json({ error: 'gitlab_project_not_found' }, 404);\n const installation = await gitlab.versionControl.registerInstallation({\n orgId: resolved.tenant.orgId,\n userId: resolved.tenant.userId,\n installation: {\n externalId: project.connectionId,\n accountName: project.accountLabel ?? 'GitLab',\n accountType: 'GitLab',\n metadata: { connection: gitlabConnection(project.connectionId) },\n },\n });\n return c.json({\n project: {\n ...project,\n installationStorageId: installation.id,\n sandboxProvider: options.sandbox ? 'custom' : 'none',\n },\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n registerApiRoute('/web/gitlab/projects/:id/prs', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const factoryProjectId = c.req.query('factoryProjectId')?.trim();\n const page = positiveId(c.req.query('page') ?? '1');\n if (!factoryProjectId || !page) return c.json({ error: 'invalid_request' }, 400);\n if ((await gitlab.resolveOrgId(factoryProjectId)) !== resolved.tenant.orgId)\n return c.json({ error: 'factory_project_not_found' }, 404);\n const linked = await gitlab.getLinkedRepository({\n orgId: resolved.tenant.orgId,\n factoryProjectId,\n projectRepositoryId: c.req.param('id'),\n });\n if (!linked) return c.json({ error: 'project_repository_not_found' }, 404);\n const projectId = positiveId(linked.repository.externalId);\n if (!projectId) return c.json({ error: 'invalid_gitlab_project' }, 502);\n try {\n const target = await gitlab.versionControl.getRepositoryTarget({\n orgId: resolved.tenant.orgId,\n repositoryId: linked.repository.id,\n });\n const result = await gitlab.versionControl.listPullRequests({\n ...target,\n includeDrafts: false,\n cursor: String(page),\n });\n await ingestListedEvents(\n result.pullRequests.flatMap(pr =>\n listedMergeRequestEvents({ host: linked.host, projectId, projectPath: linked.repository.slug }, pr),\n ),\n options.ingestFactoryEvent,\n );\n return c.json({\n pullRequests: result.pullRequests.map(pr => ({\n number: Number(pr.id),\n externalId: mergeRequestSourceKey(linked.host, projectId, Number(pr.id)),\n title: pr.title,\n url: pr.url,\n author: pr.author,\n assignees: pr.assignees ?? [],\n requestedReviewers: pr.requestedReviewers ?? [],\n labels: pr.labels ?? [],\n baseBranch: pr.baseBranch,\n headBranch: pr.headBranch,\n createdAt: pr.createdAt,\n updatedAt: pr.updatedAt,\n })),\n nextPage: result.nextCursor === null ? null : Number(result.nextCursor),\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n registerApiRoute('/web/gitlab/projects/:id/prs/:number', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const factoryProjectId = c.req.query('factoryProjectId')?.trim();\n const number = positiveId(c.req.param('number'));\n if (!factoryProjectId || !number) return c.json({ error: 'invalid_request' }, 400);\n if ((await gitlab.resolveOrgId(factoryProjectId)) !== resolved.tenant.orgId)\n return c.json({ error: 'factory_project_not_found' }, 404);\n const linked = await gitlab.getLinkedRepository({\n orgId: resolved.tenant.orgId,\n factoryProjectId,\n projectRepositoryId: c.req.param('id'),\n });\n if (!linked) return c.json({ error: 'project_repository_not_found' }, 404);\n try {\n const target = await gitlab.versionControl.getRepositoryTarget({\n orgId: resolved.tenant.orgId,\n repositoryId: linked.repository.id,\n });\n const pr = await gitlab.versionControl.getPullRequest({ ...target, pullRequestId: String(number) });\n if (!pr) return c.json({ error: 'merge_request_not_found' }, 404);\n return c.json({\n number,\n title: pr.title,\n url: pr.url,\n author: pr.author,\n assignees: pr.assignees ?? [],\n requestedReviewers: pr.requestedReviewers ?? [],\n baseBranch: pr.baseBranch,\n headBranch: pr.headBranch,\n createdAt: pr.createdAt,\n updatedAt: pr.updatedAt,\n description: pr.body,\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n );\n }\n\n if (gitlab && auth && intake) {\n routes.push(\n registerApiRoute('/web/gitlab/issues', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const factoryProjectId = c.req.query('factoryProjectId')?.trim();\n if (!factoryProjectId) return c.json({ error: 'invalid_factory_project_id' }, 400);\n const board = c.req.query('board')?.trim();\n if (!board) return c.json({ error: 'invalid_board' }, 400);\n if ((await gitlab.resolveOrgId(factoryProjectId)) !== resolved.tenant.orgId) {\n return c.json({ error: 'factory_project_not_found' }, 404);\n }\n\n await intake.ensureReady();\n const config = await intake.getConfig({ orgId: resolved.tenant.orgId, integrationIds: ['gitlab'] });\n const selection = config.gitlab!;\n if (!selection.enabled) {\n return c.json(\n { error: 'gitlab_intake_disabled', message: 'GitLab intake is turned off in Settings.' },\n 404,\n );\n }\n const selected = new Set(selection.sourceIds ?? []);\n const sourceIds = [\n ...new Set(\n (await intake.listBindings({ orgId: resolved.tenant.orgId, integrationId: 'gitlab' }))\n .filter(\n binding =>\n binding.factoryProjectId === factoryProjectId &&\n binding.board === board &&\n selected.has(binding.sourceId),\n )\n .map(binding => binding.sourceId),\n ),\n ];\n if (sourceIds.length === 0) return c.json({ issues: [], nextCursor: null });\n\n try {\n const result = await gitlab.intake.listIssues({\n connection: { type: 'oauth', accessToken: 'gitlab-route' },\n sourceIds,\n cursor: c.req.query('after')?.trim() || undefined,\n });\n await ingestListedEvents(result.issues.map(listedIssueEvent), options.ingestFactoryEvent);\n return c.json({\n ...result,\n issues: result.issues.map(issue => {\n const source = decodeSourceId(issue.sourceId ?? '');\n const issueIid = Number(issue.id);\n if (!source || !Number.isSafeInteger(issueIid) || issueIid <= 0) {\n throw new Error('GitLab returned an invalid routed issue reference.');\n }\n return { ...issue, externalId: encodeIssueReference({ ...source, issueIid }) };\n }),\n });\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n );\n\n routes.push(\n registerApiRoute('/web/gitlab/issues/:issueId', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const factoryProjectId = c.req.query('factoryProjectId')?.trim();\n if (!factoryProjectId) return c.json({ error: 'invalid_factory_project_id' }, 400);\n if ((await gitlab.resolveOrgId(factoryProjectId)) !== resolved.tenant.orgId) {\n return c.json({ error: 'factory_project_not_found' }, 404);\n }\n const issueId = c.req.param('issueId')?.trim();\n const issueReference = issueId ? decodeIssueReference(issueId) : null;\n if (!issueReference) return c.json({ error: 'invalid_gitlab_issue_id' }, 400);\n\n const { host, connectionId, projectId, projectPath } = issueReference;\n const sourceId = host\n ? encodeSourceId({ host, projectId })\n : encodeSourceId({ connectionId, projectId, projectPath });\n await intake.ensureReady();\n const config = await intake.getConfig({ orgId: resolved.tenant.orgId, integrationIds: ['gitlab'] });\n const selection = config.gitlab!;\n const selected = new Set(selection.sourceIds ?? []);\n const routed =\n selection.enabled &&\n selected.has(sourceId) &&\n (await intake.listBindings({ orgId: resolved.tenant.orgId, integrationId: 'gitlab' })).some(\n binding => binding.factoryProjectId === factoryProjectId && binding.sourceId === sourceId,\n );\n if (!routed) return c.json({ error: 'gitlab_issue_not_routed' }, 404);\n\n try {\n const issue = await gitlab.intake.getIssue({\n connection: { type: 'oauth', accessToken: 'gitlab-route' },\n issueId,\n });\n if (!issue) return c.json({ error: 'gitlab_issue_not_found' }, 404);\n return c.json(issue);\n } catch (error) {\n return gitlabFetchError(loose(c), error);\n }\n },\n }),\n );\n }\n\n if (gitlab && auth) {\n routes.push(\n registerApiRoute('/web/gitlab/subscriptions', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n await auth.ensureUser(loose(c));\n const tenant = auth.tenant(loose(c));\n if (!tenant?.orgId) return c.json({ error: 'unauthorized' }, 401);\n\n // Sessions read by session id; resourceId is the older address.\n const sessionId = c.req.query('sessionId');\n const resourceId = c.req.query('resourceId');\n const threadId = c.req.query('threadId');\n const target = !threadId\n ? null\n : sessionId\n ? { orgId: tenant.orgId, sessionId, threadId }\n : resourceId\n ? { orgId: tenant.orgId, resourceId, threadId }\n : null;\n if (!target) return c.json({ error: 'sessionId (or resourceId) and threadId are required' }, 400);\n\n const subscriptions = await listMergeRequestSubscriptionsForThread(target, gitlab.integrationStorage);\n return c.json({\n subscriptions: subscriptions.map(subscription => ({\n id: subscription.id,\n repoFullName: subscription.data.projectPath,\n pullRequestNumber: Number(subscription.data.changeRequestId),\n status: subscription.status,\n url: mergeRequestUrl(\n subscription.data.host,\n subscription.data.projectPath,\n subscription.data.changeRequestId,\n ),\n })),\n });\n },\n }),\n );\n }\n\n routes.push(\n registerApiRoute('/web/gitlab/webhook', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const result = await handleGitLabWebhook(loose(c), {\n webhookSecret: options.webhookSecret,\n ingestFactoryEvent: options.ingestFactoryEvent,\n ...(options.controller && gitlab\n ? {\n controller: options.controller,\n gitlab,\n onTargetError: (subscription, error) => {\n console.warn(\n `[GitLab Webhook] Delivery failed for subscription ${subscription.id} (${subscription.resourceId}/${subscription.threadId}).`,\n error,\n );\n },\n }\n : {}),\n });\n return c.json(result.body, result.status);\n },\n }),\n );\n return routes;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/integrations/gitlab/rules.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAS3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AACrF,OAAO,KAAK,EAEV,0BAA0B,EAC3B,MAAM,8CAA8C,CAAC;AAEtD,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC9F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,KAAK,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;AAoHtE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,8BAA8B,CAAC,CAAC,kBAAkB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3F,2BAA2B,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACpH,yBAAyB,CACvB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,GAAG,eAAe,EAC/B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAChC;AAED,UAAU,kBAAkB;IAC1B,MAAM,EAAE,sBAAsB,CAAC;IAC/B,aAAa,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,EAAE,sBAAsB,CAAC;IACjC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,aAAa,CAAC;CACvB;AAOD,qBAAa,WAAW;;IACV,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,kBAAkB;IAElD,MAAM,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/integrations/gitlab/rules.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAS3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AACrF,OAAO,KAAK,EAEV,0BAA0B,EAC3B,MAAM,8CAA8C,CAAC;AAEtD,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC9F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,KAAK,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;AAoHtE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,8BAA8B,CAAC,CAAC,kBAAkB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3F,2BAA2B,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACpH,yBAAyB,CACvB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,GAAG,eAAe,EAC/B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAChC;AAED,UAAU,kBAAkB;IAC1B,MAAM,EAAE,sBAAsB,CAAC;IAC/B,aAAa,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,EAAE,sBAAsB,CAAC;IACjC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,aAAa,CAAC;CACvB;AAOD,qBAAa,WAAW;;IACV,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,kBAAkB;IAElD,MAAM,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC;CA6iB9E;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,kBAAkB,GAC1B,CAAC,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,CAYhE"}
|
|
@@ -5,7 +5,7 @@ import { WorkItemUpdateConflictError } from "../../storage/domains/work-items/ba
|
|
|
5
5
|
import { hasExplicitRuleOverride, selectEventRule } from "../../rules/event-rules.js";
|
|
6
6
|
import { recordPullRequestHead } from "../pull-request-head.js";
|
|
7
7
|
import { encodeIssueReference, encodeSourceId } from "./integration.js";
|
|
8
|
-
|
|
8
|
+
// src/integrations/gitlab/rules.ts
|
|
9
9
|
const RULE_TIMEOUT_MS = 5e3;
|
|
10
10
|
function object(value) {
|
|
11
11
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
@@ -221,6 +221,7 @@ var GitLabRules = class {
|
|
|
221
221
|
const lastCommit = object(mergeRequest?.last_commit);
|
|
222
222
|
const headSha = string(lastCommit?.id)?.toLowerCase();
|
|
223
223
|
const headAt = timestamp(mergeRequest?.updated_at) ?? timestamp(lastCommit?.timestamp);
|
|
224
|
+
const unchangedListedHead = parsed.deliveryId.startsWith("poll:merge-request-head:") && headAt !== void 0 && reviewItem?.metadata?.pullRequestHeadSha === headSha && (reviewItem?.metadata?.pullRequestHeadAt !== headAt || reviewItem?.metadata?.pullRequestHeadDeliveryId !== parsed.deliveryId);
|
|
224
225
|
let pushedReviewItem = reviewItem;
|
|
225
226
|
if (event === "mergeRequestUpdated" && headSha && reviewItem) {
|
|
226
227
|
const parent = items.find((item) => item.id === reviewItem.parentWorkItemId);
|
|
@@ -228,7 +229,8 @@ var GitLabRules = class {
|
|
|
228
229
|
orgId: reviewItem.orgId,
|
|
229
230
|
id: reviewItem.id,
|
|
230
231
|
headSha,
|
|
231
|
-
headAt
|
|
232
|
+
headAt,
|
|
233
|
+
deliveryId: parsed.deliveryId.startsWith("poll:merge-request-head:") ? parsed.deliveryId : void 0
|
|
232
234
|
});
|
|
233
235
|
if (parent) await recordPullRequestHead(this.options.storage, {
|
|
234
236
|
orgId: parent.orgId,
|
|
@@ -241,6 +243,7 @@ var GitLabRules = class {
|
|
|
241
243
|
orgId: reviewItem.orgId,
|
|
242
244
|
id: reviewItem.id
|
|
243
245
|
}) ?? reviewItem;
|
|
246
|
+
if (unchangedListedHead) return { status: "ignored" };
|
|
244
247
|
}
|
|
245
248
|
const candidates = event === "mergeRequestMerged" ? [...new Map([reviewItem, authoringItem].filter(Boolean).map((item) => [item.id, item])).values()] : event === "mergeRequestCommented" ? [authoringItem ?? reviewItem] : event === "mergeRequestOpened" ? [authoringItem, ...authoringItem ? [authoringItem] : []] : event.startsWith("mergeRequest") ? [pushedReviewItem ?? authoringItem] : [issueItem];
|
|
246
249
|
const results = [];
|
|
@@ -503,7 +506,6 @@ function attachGitLabRules(gitlab, context) {
|
|
|
503
506
|
});
|
|
504
507
|
return (event) => rules.ingest(event);
|
|
505
508
|
}
|
|
506
|
-
//#endregion
|
|
507
509
|
export { GitLabRules, attachGitLabRules };
|
|
508
510
|
|
|
509
511
|
//# sourceMappingURL=rules.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","names":[],"sources":["../../../src/integrations/gitlab/rules.ts"],"sourcesContent":["import {\n boardEventHandlers,\n boardForWorkItem,\n eventBoardId,\n rulePhaseField,\n withBoardClosure,\n} from '../../boards/index.js';\nimport type { BoardRegistry } from '../../boards/index.js';\nimport { hasExplicitRuleOverride, selectEventRule } from '../../rules/event-rules.js';\nimport type {\n FactoryGitLabEventName,\n FactoryGitLabRuleContext,\n FactoryRuleActor,\n FactoryRuleDecision,\n} from '../../rules/types.js';\nimport { assertFactoryDecisionTarget, validateFactoryRuleDecisions } from '../../rules/validation.js';\nimport type { IntakeStorage } from '../../storage/domains/intake/base.js';\nimport type { FactoryProjectsStorage } from '../../storage/domains/projects/base.js';\nimport type {\n ExternalRepositoryProjectTarget,\n SourceControlStorageHandle,\n} from '../../storage/domains/source-control/base.js';\nimport { WorkItemUpdateConflictError } from '../../storage/domains/work-items/base.js';\nimport type { WorkItemRow, WorkItemsStorage } from '../../storage/domains/work-items/base.js';\nimport type { IntegrationContext } from '../base.js';\nimport { recordPullRequestHead } from '../pull-request-head.js';\nimport type { GitLabEventRules } from './default-rules.js';\nimport { encodeIssueReference, encodeSourceId, GITLAB_TRUSTED_ACCESS_LEVEL } from './integration.js';\nimport type { ParsedGitLabWebhook } from './webhook.js';\n\nconst RULE_TIMEOUT_MS = 5_000;\n\ntype IngressStatus = 'ignored' | 'committed' | 'replayed' | 'missing';\n\nfunction object(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction string(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction number(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\n/** GitLab sends `2024-01-02T03:04:05Z`, `2024-01-02 03:04:05 UTC` or `2024-01-02 03:04:05 +0000`. */\nfunction timestamp(value: unknown): number | undefined {\n const text = string(value);\n if (!text) return undefined;\n const spaced = /^(\\d{4}-\\d{2}-\\d{2}) (\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?) (?:UTC|([+-]\\d{2}):?(\\d{2}))$/.exec(text);\n const parsed = Date.parse(\n spaced ? `${spaced[1]}T${spaced[2]}${spaced[3] ? `${spaced[3]}:${spaced[4]}` : 'Z'}` : text,\n );\n return Number.isNaN(parsed) ? undefined : parsed;\n}\n\nfunction boolean(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined;\n}\n\nfunction usernames(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap(entry => {\n const username = string(object(entry)?.username);\n return username ? [username] : [];\n });\n}\n\nfunction labelNames(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap(entry => {\n if (typeof entry === 'string') return entry ? [entry] : [];\n const title = string(object(entry)?.title) ?? string(object(entry)?.name);\n return title ? [title] : [];\n });\n}\n\nfunction labelColors(value: unknown): Record<string, string> {\n if (!Array.isArray(value)) return {};\n return Object.fromEntries(\n value.flatMap(entry => {\n const label = object(entry);\n const name = string(label?.title) ?? string(label?.name);\n const color = string(label?.color);\n return name && color ? [[name, color]] : [];\n }),\n );\n}\n\nfunction eventName(parsed: ParsedGitLabWebhook): FactoryGitLabEventName | undefined {\n const attributes = object(parsed.payload.object_attributes);\n const action = string(attributes?.action)?.toLowerCase();\n if (parsed.event === 'Issue Hook') {\n if (action === 'open' || action === 'reopen') return 'issueOpened';\n if (action === 'close') return 'issueClosed';\n return 'issueUpdated';\n }\n if (parsed.event === 'Note Hook') {\n const noteableType = string(attributes?.noteable_type);\n if (noteableType === 'Issue') return 'issueCommented';\n if (noteableType === 'MergeRequest') return 'mergeRequestCommented';\n return;\n }\n if (parsed.event !== 'Merge Request Hook') return;\n if (action === 'open' || action === 'reopen') return 'mergeRequestOpened';\n if (action === 'merge') return 'mergeRequestMerged';\n if (action === 'close') return 'mergeRequestClosed';\n return 'mergeRequestUpdated';\n}\n\nfunction normalizeHost(host: string): string {\n return host.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nfunction hostFromPayload(parsed: ParsedGitLabWebhook): string | undefined {\n const declaredHost = parsed.instanceHost ? normalizeHost(parsed.instanceHost) : undefined;\n const projectUrl = string(object(parsed.payload.project)?.web_url);\n if (!projectUrl) return declaredHost;\n try {\n const payloadHost = normalizeHost(new URL(projectUrl).host);\n if (declaredHost && declaredHost !== payloadHost) return undefined;\n return payloadHost;\n } catch {\n return undefined;\n }\n}\n\nfunction mergeRequestSourceKey(host: string, projectId: number, mergeRequestIid: number): string {\n return `gitlab-pr:${Buffer.from(JSON.stringify({ version: 1, host, projectId, mergeRequestIid }), 'utf8').toString('base64url')}`;\n}\n\nasync function withRuleTimeout<T>(promise: Promise<T>): Promise<T> {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timeout = setTimeout(() => reject(new Error('FACTORY_RULE_TIMEOUT')), RULE_TIMEOUT_MS);\n }),\n ]);\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\nconst MAX_STALE_RULE_ATTEMPTS = 3;\n\nexport interface GitLabRulesIntegration {\n readonly rules: GitLabEventRules;\n resolveActiveConnectionForHost?(storedConnectionId: string, host: string): Promise<string>;\n getProjectMemberAccessLevel(connectionId: string, projectId: string, username: string): Promise<number | undefined>;\n getWorkItemAuthorUsername(\n connectionId: string,\n projectId: string,\n kind: 'issue' | 'merge_request',\n iid: number,\n ): Promise<string | undefined>;\n}\n\ninterface GitLabRulesOptions {\n gitlab: GitLabRulesIntegration;\n sourceControl: SourceControlStorageHandle;\n projects: FactoryProjectsStorage;\n storage: WorkItemsStorage;\n intake: IntakeStorage;\n configVersion: string;\n boards: BoardRegistry;\n}\n\ninterface ProjectTarget {\n target: ExternalRepositoryProjectTarget;\n connectionIds: string[];\n}\n\nexport class GitLabRules {\n constructor(private readonly options: GitLabRulesOptions) {}\n\n async ingest(parsed: ParsedGitLabWebhook): Promise<{ status: IngressStatus }> {\n const event = eventName(parsed);\n const project = object(parsed.payload.project);\n const projectId = number(project?.id);\n const projectPath = string(project?.path_with_namespace);\n const host = hostFromPayload(parsed);\n const username = string(parsed.payload.user_username) ?? string(object(parsed.payload.user)?.username);\n if (!event || !projectId || !projectPath || !host || !username) return { status: 'ignored' };\n\n const targets = await this.#targets(String(projectId), host);\n if (targets.length === 0) return { status: 'ignored' };\n const results: Array<{ status: IngressStatus }> = [];\n for (const target of targets) {\n results.push(await this.#ingestProject(parsed, event, projectId, projectPath, host, username, target));\n }\n if (results.some(result => result.status === 'committed')) return { status: 'committed' };\n if (results.some(result => result.status === 'replayed')) return { status: 'replayed' };\n return results[0] ?? { status: 'ignored' };\n }\n\n async #targets(repositoryExternalId: string, host: string): Promise<ProjectTarget[]> {\n const grouped = new Map<string, ProjectTarget>();\n const keys = (await this.options.sourceControl.projectRepositories.listConfiguredExternalKeys()).filter(\n key => key.repositoryExternalId === repositoryExternalId,\n );\n for (const key of keys) {\n const targets = await this.options.sourceControl.projectRepositories.listByExternalRepository({\n installationExternalId: key.installationExternalId,\n repositoryExternalId,\n });\n for (const target of targets) {\n const installation = await this.options.sourceControl.installations.findByExternalId({\n orgId: target.orgId,\n externalId: key.installationExternalId,\n });\n const installationHost = string(installation?.providerMetadata.host);\n if (!installationHost || normalizeHost(installationHost) !== normalizeHost(host)) continue;\n const id = `${target.orgId}:${target.factoryProjectId}`;\n const current = grouped.get(id);\n if (current) {\n if (!current.connectionIds.includes(key.installationExternalId)) {\n current.connectionIds.push(key.installationExternalId);\n }\n } else {\n grouped.set(id, { target, connectionIds: [key.installationExternalId] });\n }\n }\n }\n return [...grouped.values()];\n }\n\n async #ingestProject(\n parsed: ParsedGitLabWebhook,\n event: FactoryGitLabEventName,\n projectId: number,\n projectPath: string,\n host: string,\n username: string,\n target: ProjectTarget,\n ): Promise<{ status: IngressStatus }> {\n const factoryProject = await this.options.projects.get({\n orgId: target.target.orgId,\n id: target.target.factoryProjectId,\n });\n if (!factoryProject) return { status: 'missing' };\n\n const sourceId = encodeSourceId({ host, projectId: String(projectId) });\n const config = await this.options.intake.getConfig({\n orgId: target.target.orgId,\n integrationIds: ['gitlab'],\n });\n if (!config.gitlab?.enabled || !config.gitlab.sourceIds?.includes(sourceId)) return { status: 'ignored' };\n const binding = (\n await this.options.intake.listBindings({ orgId: target.target.orgId, integrationId: 'gitlab' })\n ).find(\n candidate => candidate.sourceId === sourceId && candidate.factoryProjectId === target.target.factoryProjectId,\n );\n if (!binding) return { status: 'ignored' };\n const board = this.options.boards.get(binding.board ?? 'work');\n if (!board) return { status: 'ignored' };\n\n const connectionIds = [\n ...new Set(\n await Promise.all(\n target.connectionIds.map(\n connectionId => this.options.gitlab.resolveActiveConnectionForHost?.(connectionId, host) ?? connectionId,\n ),\n ),\n ),\n ];\n\n const attributes = object(parsed.payload.object_attributes);\n const issue = parsed.event === 'Note Hook' ? object(parsed.payload.issue) : attributes;\n const mergeRequest = parsed.event === 'Note Hook' ? object(parsed.payload.merge_request) : attributes;\n const issueIid = number(issue?.iid);\n const mergeRequestIid = number(mergeRequest?.iid);\n const issueSourceKey = issueIid\n ? encodeIssueReference({ host, projectId: String(projectId), issueIid })\n : undefined;\n const mergeRequestKey = mergeRequestIid ? mergeRequestSourceKey(host, projectId, mergeRequestIid) : undefined;\n const items = await this.options.storage.list({\n orgId: target.target.orgId,\n factoryProjectId: target.target.factoryProjectId,\n });\n const issueItem = issueSourceKey\n ? items.find(\n item => item.externalSource?.integrationId === 'gitlab' && item.externalSource.externalId === issueSourceKey,\n )\n : undefined;\n const reviewItem = mergeRequestKey\n ? items.find(\n item => item.externalSource?.integrationId === 'gitlab' && item.externalSource.externalId === mergeRequestKey,\n )\n : undefined;\n const headBranch = string(mergeRequest?.source_branch) ?? '';\n const authoringItem = headBranch\n ? items.find(\n item =>\n item.externalSource?.type !== 'pull-request' &&\n Object.values(item.sessions).some(session => session.branch === headBranch),\n )\n : undefined;\n const actorTrusted = await this.#trusted(connectionIds, String(projectId), username);\n const eventUserId = number(object(parsed.payload.user)?.id) ?? number(parsed.payload.user_id);\n const resolveAuthor = async (\n item: Record<string, unknown> | undefined,\n kind: 'issue' | 'merge_request',\n iid: number | undefined,\n ): Promise<string | undefined> => {\n if (!item || !iid) return undefined;\n const embedded = string(object(item.author)?.username);\n if (embedded) return embedded;\n if (eventUserId && eventUserId === number(item.author_id)) return username;\n for (const connectionId of connectionIds) {\n try {\n const resolved = await this.options.gitlab.getWorkItemAuthorUsername(\n connectionId,\n String(projectId),\n kind,\n iid,\n );\n if (resolved) return resolved;\n } catch {\n // Another active credential may cover this project; otherwise leave author trust unset.\n }\n }\n return undefined;\n };\n const [issueAuthor, mergeRequestAuthor] = await Promise.all([\n resolveAuthor(issue, 'issue', issueIid),\n resolveAuthor(mergeRequest, 'merge_request', mergeRequestIid),\n ]);\n const authorTrusted = async (author: string | undefined): Promise<boolean> => {\n if (!author) return false;\n return author === username ? actorTrusted : this.#trusted(connectionIds, String(projectId), author);\n };\n const [issueAuthorTrusted, mergeRequestAuthorTrusted] = await Promise.all([\n authorTrusted(issueAuthor),\n authorTrusted(mergeRequestAuthor),\n ]);\n const actor: FactoryRuleActor = {\n type: 'gitlab',\n username,\n trusted: actorTrusted,\n factoryAuthored: false,\n };\n\n // A push moves the head a recorded review verdict was given on. Recording\n // the new head lets the verdict badge show that it is outdated, while the\n // verdict itself stays so the next pass still runs as a re-review. It is\n // recorded before the push is evaluated: the dispatcher can apply the\n // re-review transition as soon as it commits, and the pass it starts names\n // the head it covers, which must be the pushed one.\n const lastCommit = object(mergeRequest?.last_commit);\n const headSha = string(lastCommit?.id)?.toLowerCase();\n // Without an update time the commit time still orders the push; dropping\n // the write would leave the pass naming the head the last verdict covered.\n const headAt = timestamp(mergeRequest?.updated_at) ?? timestamp(lastCommit?.timestamp);\n let pushedReviewItem = reviewItem;\n if (event === 'mergeRequestUpdated' && headSha && reviewItem) {\n const parent = items.find(item => item.id === reviewItem.parentWorkItemId);\n // The authoring Work item mirrors the verdict of the merge request it has\n // out; a push to an older one must not mark its successor's verdict.\n await recordPullRequestHead(this.options.storage, {\n orgId: reviewItem.orgId,\n id: reviewItem.id,\n headSha,\n headAt,\n });\n if (parent) {\n await recordPullRequestHead(this.options.storage, {\n orgId: parent.orgId,\n id: parent.id,\n headSha,\n headAt,\n ownedPullRequestNumber: mergeRequestIid,\n });\n }\n pushedReviewItem = (await this.options.storage.get({ orgId: reviewItem.orgId, id: reviewItem.id })) ?? reviewItem;\n }\n const candidates: Array<WorkItemRow | undefined> =\n event === 'mergeRequestMerged'\n ? [...new Map([reviewItem, authoringItem].filter(Boolean).map(item => [item!.id, item!])).values()]\n : event === 'mergeRequestCommented'\n ? [authoringItem ?? reviewItem]\n : event === 'mergeRequestOpened'\n ? [authoringItem, ...(authoringItem ? [authoringItem] : [])]\n : event.startsWith('mergeRequest')\n ? [pushedReviewItem ?? authoringItem]\n : [issueItem];\n const results = [];\n for (const [index, item] of candidates.entries()) {\n results.push(\n await this.#evaluate({\n parsed,\n event,\n projectId,\n projectPath,\n host,\n actor,\n orgId: target.target.orgId,\n factoryProjectId: target.target.factoryProjectId,\n factoryProject,\n board: { board: board.id, initialPhase: board.initialPhase },\n issue,\n issueAuthor,\n issueAuthorTrusted,\n issueIid,\n issueSourceKey,\n mergeRequest,\n mergeRequestAuthor,\n mergeRequestAuthorTrusted,\n mergeRequestIid,\n mergeRequestKey,\n factoryAuthored: Boolean(authoringItem),\n item,\n ingressIdentity: `gitlab:${projectId}:${parsed.deliveryId}${index ? `:${item?.id ?? index}` : ''}`,\n // A merge request opening concerns two cards: its own Review card,\n // which the integration handler files against the authoring item,\n // and that authoring item, which its board may react to. The second\n // evaluation runs only the board handler, under an id-suffixed\n // identity so it is not dropped as a replay of the first.\n ...(event === 'mergeRequestOpened' ? { mergeRequestOpenedScope: index ? ('board' as const) : ('intake' as const) } : {}),\n }),\n );\n }\n // The authoring Work item records which merge request it has out, so the\n // Work transition policy keeps an agent from closing the work while it is\n // open. Sessions carry no repository, so a branch shared by two Work cards\n // is ambiguous and records nothing.\n const branchOwners = headBranch\n ? items.filter(\n item =>\n item.externalSource?.type !== 'pull-request' &&\n Object.values(item.sessions).some(session => session.branch === headBranch),\n )\n : [];\n if (authoringItem && mergeRequestIid && branchOwners.length === 1) {\n await this.#trackOpenMergeRequest({\n orgId: authoringItem.orgId,\n id: authoringItem.id,\n event,\n mergeRequestIid,\n eventAt: timestamp(mergeRequest?.updated_at),\n opened: string(mergeRequest?.state) === 'opened' && (actorTrusted || mergeRequestAuthorTrusted),\n headSha: string(object(mergeRequest?.last_commit)?.id)?.toLowerCase(),\n });\n }\n if (results.some(result => result.status === 'committed')) return { status: 'committed' };\n if (results.some(result => result.status === 'replayed')) return { status: 'replayed' };\n return results[0] ?? { status: 'ignored' };\n }\n\n /**\n * Records or clears the merge request a Work card has out. Each merge\n * request's last applied event time is kept on the card, so an opening that\n * is older than a close already applied (a replay, or a close delivered\n * first) is ignored, while a genuine reopen is newer and records it again.\n */\n async #trackOpenMergeRequest(input: {\n orgId: string;\n id: string;\n event: string;\n mergeRequestIid: number;\n eventAt: number | undefined;\n opened: boolean;\n headSha: string | undefined;\n }): Promise<void> {\n const settling = input.event === 'mergeRequestMerged' || input.event === 'mergeRequestClosed';\n if (input.event !== 'mergeRequestOpened' && !settling) return;\n const key = String(input.mergeRequestIid);\n for (let attempt = 0; attempt < 3; attempt++) {\n const item = await this.options.storage.get({ orgId: input.orgId, id: input.id });\n if (!item) return;\n const events = object(item.metadata?.mergeRequestEvents) ?? {};\n const last = object(events[key]);\n const lastAt = number(last?.at);\n if (input.eventAt !== undefined && lastAt !== undefined && lastAt >= input.eventAt) return;\n // Without a timestamp, only an opening that no close has settled is trusted.\n if (input.eventAt === undefined && !settling && last?.open === false) return;\n if (!settling && !input.opened) return;\n const recorded = item.metadata?.openPullRequestNumber;\n const patch: Record<string, unknown> = {\n mergeRequestEvents: { ...events, [key]: { at: input.eventAt ?? lastAt ?? null, open: !settling } },\n };\n if (!settling) {\n // A head recorded for an earlier merge request must not mark this one's\n // verdict outdated. A replayed opening of the merge request already\n // recorded keeps the head its pushes left.\n if (recorded !== input.mergeRequestIid) {\n patch.pullRequestHeadSha = input.headSha ?? null;\n patch.pullRequestHeadAt = input.eventAt ?? null;\n }\n patch.openPullRequestNumber = input.mergeRequestIid;\n } else if (recorded === input.mergeRequestIid) {\n patch.openPullRequestNumber = null;\n if (input.event === 'mergeRequestMerged' && typeof item.metadata?.reviewVerdict === 'string') {\n patch.reviewVerdict = null;\n }\n }\n try {\n await this.options.storage.update({\n orgId: item.orgId,\n id: item.id,\n userId: 'factory-rule-dispatcher',\n expectedRevision: item.revision,\n patch: { metadata: patch },\n });\n return;\n } catch (error) {\n if (!(error instanceof WorkItemUpdateConflictError)) throw error;\n }\n }\n }\n\n async #trusted(connectionIds: string[], projectId: string, username: string): Promise<boolean> {\n for (const connectionId of connectionIds) {\n try {\n const level = await this.options.gitlab.getProjectMemberAccessLevel(connectionId, projectId, username);\n if (level !== undefined) return level >= GITLAB_TRUSTED_ACCESS_LEVEL;\n } catch {\n // Try another active credential covering the same canonical project; otherwise fail closed.\n }\n }\n return false;\n }\n\n async #evaluate(\n input: {\n parsed: ParsedGitLabWebhook;\n event: FactoryGitLabEventName;\n projectId: number;\n projectPath: string;\n host: string;\n actor: FactoryRuleActor;\n orgId: string;\n factoryProjectId: string;\n factoryProject: { createdAt: Date };\n board: { board: string; initialPhase: string };\n issue: Record<string, unknown> | undefined;\n issueAuthor: string | undefined;\n issueAuthorTrusted: boolean;\n issueIid: number | undefined;\n issueSourceKey: string | undefined;\n mergeRequest: Record<string, unknown> | undefined;\n mergeRequestAuthor: string | undefined;\n mergeRequestAuthorTrusted: boolean;\n mergeRequestIid: number | undefined;\n mergeRequestKey: string | undefined;\n factoryAuthored: boolean;\n item: WorkItemRow | undefined;\n ingressIdentity: string;\n mergeRequestOpenedScope?: 'intake' | 'board';\n },\n attempt = 1,\n ): Promise<{ status: IngressStatus }> {\n const note = object(input.parsed.payload.object_attributes);\n const issueAuthor = input.issueAuthor;\n const mergeRequestAuthor = input.mergeRequestAuthor;\n const mergeRequestState = string(input.mergeRequest?.state);\n const context: FactoryGitLabRuleContext = {\n tenant: { orgId: input.orgId, projectId: input.factoryProjectId },\n actor: input.actor,\n ingress: { type: 'gitlab', id: input.ingressIdentity },\n cause: `gitlab.${input.event}`,\n causalChain: [],\n configVersion: this.options.configVersion,\n ...(input.item\n ? {\n item: {\n id: input.item.id,\n source:\n input.item.externalSource?.type === 'pull-request'\n ? ('gitlab-pr' as const)\n : input.item.externalSource?.integrationId === 'gitlab'\n ? ('gitlab-issue' as const)\n : ('manual' as const),\n sourceKey: input.item.externalSource?.externalId ?? null,\n parentWorkItemId: input.item.parentWorkItemId,\n title: input.item.title,\n url: input.item.externalSource?.url ?? null,\n stages: input.item.stages,\n acceptedAt: input.item.acceptedAt,\n metadata: input.item.metadata,\n },\n board: boardForWorkItem(input.item),\n itemRevision: input.item.revision,\n ...withBoardClosure(this.options.boards, input.item),\n ...rulePhaseField(this.options.boards, input.item),\n }\n : {}),\n intake: input.board,\n event: input.event,\n deliveryId: input.parsed.deliveryId,\n factory: { createdAt: input.factoryProject.createdAt.toISOString() },\n repository: { id: input.projectId, fullName: input.projectPath, host: input.host },\n ...(input.issueIid && input.issueSourceKey && string(input.issue?.title)\n ? {\n issue: {\n number: input.issueIid,\n sourceKey: input.issueSourceKey,\n title: string(input.issue?.title)!,\n url:\n string(input.issue?.url) ??\n string(input.issue?.web_url) ??\n `https://${input.host}/${input.projectPath}/-/issues/${input.issueIid}`,\n ...(string(input.issue?.created_at) ? { createdAt: string(input.issue?.created_at) } : {}),\n ...(string(input.issue?.updated_at) ? { updatedAt: string(input.issue?.updated_at) } : {}),\n assignees: usernames(input.parsed.payload.assignees ?? input.issue?.assignees),\n labels: labelNames(input.issue?.labels ?? input.parsed.payload.labels),\n labelColors: labelColors(input.issue?.labels ?? input.parsed.payload.labels),\n state: string(input.issue?.state) === 'closed' ? ('closed' as const) : ('open' as const),\n ...(issueAuthor ? { author: issueAuthor } : {}),\n authorTrusted: input.issueAuthorTrusted,\n },\n }\n : {}),\n ...(input.parsed.event === 'Note Hook' && number(note?.id)\n ? {\n note: {\n id: number(note?.id)!,\n ...(string(note?.note) ? { body: string(note?.note) } : {}),\n ...(string(note?.url) ? { url: string(note?.url) } : {}),\n ...(string(object(input.parsed.payload.user)?.username)\n ? { author: string(object(input.parsed.payload.user)?.username) }\n : {}),\n ...(string(note?.created_at) ? { createdAt: string(note?.created_at) } : {}),\n ...(string(note?.updated_at) ? { updatedAt: string(note?.updated_at) } : {}),\n },\n }\n : {}),\n ...(input.mergeRequestIid && input.mergeRequestKey && string(input.mergeRequest?.title)\n ? {\n mergeRequest: {\n number: input.mergeRequestIid,\n sourceKey: input.mergeRequestKey,\n title: string(input.mergeRequest?.title)!,\n url:\n string(input.mergeRequest?.url) ??\n string(input.mergeRequest?.web_url) ??\n `https://${input.host}/${input.projectPath}/-/merge_requests/${input.mergeRequestIid}`,\n ...(string(input.mergeRequest?.created_at) ? { createdAt: string(input.mergeRequest?.created_at) } : {}),\n state:\n mergeRequestState === 'closed' || mergeRequestState === 'merged'\n ? ('closed' as const)\n : ('open' as const),\n draft: boolean(input.mergeRequest?.draft) ?? boolean(input.mergeRequest?.work_in_progress) ?? false,\n merged: input.event === 'mergeRequestMerged' || mergeRequestState === 'merged',\n assignees: usernames(input.parsed.payload.assignees ?? input.mergeRequest?.assignees),\n reviewers: usernames(input.parsed.payload.reviewers ?? input.mergeRequest?.reviewers),\n labels: labelNames(input.mergeRequest?.labels ?? input.parsed.payload.labels),\n labelColors: labelColors(input.mergeRequest?.labels ?? input.parsed.payload.labels),\n ...(mergeRequestAuthor ? { author: mergeRequestAuthor } : {}),\n authorTrusted: input.mergeRequestAuthorTrusted,\n factoryAuthored: input.factoryAuthored,\n headBranch: string(input.mergeRequest?.source_branch) ?? '',\n baseBranch: string(input.mergeRequest?.target_branch) ?? '',\n },\n }\n : {}),\n };\n const boardRules = boardEventHandlers(\n this.options.boards,\n input.mergeRequestOpenedScope === 'intake' ? undefined : eventBoardId(context),\n 'gitlab',\n );\n const rule =\n input.mergeRequestOpenedScope === 'board'\n ? hasExplicitRuleOverride(this.options.gitlab.rules, input.event)\n ? undefined\n : boardRules?.mergeRequestOpened\n : selectEventRule(this.options.gitlab.rules, boardRules, input.event);\n // Without a board handler the authoring card has nothing to answer; skip\n // recording an empty evaluation for it.\n if (input.mergeRequestOpenedScope === 'board' && !rule) return { status: 'ignored' };\n let decision: FactoryRuleDecision | void;\n let decisions: Record<string, unknown>[] = [];\n let outcome: { status: 'accepted' | 'rejected'; code?: string; reason?: string } = { status: 'accepted' };\n try {\n decision = rule ? await withRuleTimeout(Promise.resolve(rule(Object.freeze(context)))) : undefined;\n if (decision?.type === 'reject') {\n outcome = { status: 'rejected', code: decision.code, reason: decision.reason };\n } else if (decision) {\n decisions = validateFactoryRuleDecisions([decision]).map(entry => {\n assertFactoryDecisionTarget(\n entry,\n this.options.boards,\n input.item ? boardForWorkItem(input.item) : undefined,\n );\n return { ...entry };\n });\n }\n } catch (error) {\n const timedOut = error instanceof Error && error.message === 'FACTORY_RULE_TIMEOUT';\n outcome = {\n status: 'rejected',\n code: timedOut ? 'timeout' : 'rule_error',\n reason: timedOut\n ? 'Factory rule evaluation timed out.'\n : error instanceof Error\n ? error.message.slice(0, 2_000)\n : 'Factory GitLab rule failed.',\n };\n }\n\n const committed = await this.options.storage.commitRuleEvaluation({\n orgId: input.orgId,\n factoryProjectId: input.factoryProjectId,\n workItemId: input.item?.id ?? null,\n ingress: { identity: input.ingressIdentity, triggerType: `gitlab.${input.event}` },\n configVersion: this.options.configVersion,\n expectedRevision: input.item?.revision ?? null,\n actor: { ...input.actor },\n outcome,\n decisions,\n causalChain: [],\n now: new Date(),\n });\n if (committed.status === 'stale') {\n // Nothing was persisted: re-read the item and evaluate again at its fresh revision.\n if (attempt >= MAX_STALE_RULE_ATTEMPTS) {\n throw new Error(`Factory GitLab rule evaluation for ${input.ingressIdentity} kept losing revision races.`);\n }\n const fresh = input.item ? await this.options.storage.get({ orgId: input.orgId, id: input.item.id }) : null;\n if (input.item && !fresh) return { status: 'missing' };\n return this.#evaluate({ ...input, item: fresh ?? undefined }, attempt + 1);\n }\n return { status: committed.status };\n }\n}\n\nexport function attachGitLabRules(\n gitlab: GitLabRulesIntegration,\n context: IntegrationContext,\n): ((event: ParsedGitLabWebhook) => Promise<unknown>) | undefined {\n if (!context.runtime) return undefined;\n const rules = new GitLabRules({\n gitlab,\n sourceControl: context.storage.sourceControl,\n projects: context.storage.projects,\n storage: context.runtime.workItems,\n intake: context.storage.intake,\n configVersion: context.runtime.configVersion,\n boards: context.runtime.boards,\n });\n return event => rules.ingest(event);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rules.js","names":[],"sources":["../../../src/integrations/gitlab/rules.ts"],"sourcesContent":["import {\n boardEventHandlers,\n boardForWorkItem,\n eventBoardId,\n rulePhaseField,\n withBoardClosure,\n} from '../../boards/index.js';\nimport type { BoardRegistry } from '../../boards/index.js';\nimport { hasExplicitRuleOverride, selectEventRule } from '../../rules/event-rules.js';\nimport type {\n FactoryGitLabEventName,\n FactoryGitLabRuleContext,\n FactoryRuleActor,\n FactoryRuleDecision,\n} from '../../rules/types.js';\nimport { assertFactoryDecisionTarget, validateFactoryRuleDecisions } from '../../rules/validation.js';\nimport type { IntakeStorage } from '../../storage/domains/intake/base.js';\nimport type { FactoryProjectsStorage } from '../../storage/domains/projects/base.js';\nimport type {\n ExternalRepositoryProjectTarget,\n SourceControlStorageHandle,\n} from '../../storage/domains/source-control/base.js';\nimport { WorkItemUpdateConflictError } from '../../storage/domains/work-items/base.js';\nimport type { WorkItemRow, WorkItemsStorage } from '../../storage/domains/work-items/base.js';\nimport type { IntegrationContext } from '../base.js';\nimport { recordPullRequestHead } from '../pull-request-head.js';\nimport type { GitLabEventRules } from './default-rules.js';\nimport { encodeIssueReference, encodeSourceId, GITLAB_TRUSTED_ACCESS_LEVEL } from './integration.js';\nimport type { ParsedGitLabWebhook } from './webhook.js';\n\nconst RULE_TIMEOUT_MS = 5_000;\n\ntype IngressStatus = 'ignored' | 'committed' | 'replayed' | 'missing';\n\nfunction object(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction string(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction number(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\n/** GitLab sends `2024-01-02T03:04:05Z`, `2024-01-02 03:04:05 UTC` or `2024-01-02 03:04:05 +0000`. */\nfunction timestamp(value: unknown): number | undefined {\n const text = string(value);\n if (!text) return undefined;\n const spaced = /^(\\d{4}-\\d{2}-\\d{2}) (\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?) (?:UTC|([+-]\\d{2}):?(\\d{2}))$/.exec(text);\n const parsed = Date.parse(\n spaced ? `${spaced[1]}T${spaced[2]}${spaced[3] ? `${spaced[3]}:${spaced[4]}` : 'Z'}` : text,\n );\n return Number.isNaN(parsed) ? undefined : parsed;\n}\n\nfunction boolean(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined;\n}\n\nfunction usernames(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap(entry => {\n const username = string(object(entry)?.username);\n return username ? [username] : [];\n });\n}\n\nfunction labelNames(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap(entry => {\n if (typeof entry === 'string') return entry ? [entry] : [];\n const title = string(object(entry)?.title) ?? string(object(entry)?.name);\n return title ? [title] : [];\n });\n}\n\nfunction labelColors(value: unknown): Record<string, string> {\n if (!Array.isArray(value)) return {};\n return Object.fromEntries(\n value.flatMap(entry => {\n const label = object(entry);\n const name = string(label?.title) ?? string(label?.name);\n const color = string(label?.color);\n return name && color ? [[name, color]] : [];\n }),\n );\n}\n\nfunction eventName(parsed: ParsedGitLabWebhook): FactoryGitLabEventName | undefined {\n const attributes = object(parsed.payload.object_attributes);\n const action = string(attributes?.action)?.toLowerCase();\n if (parsed.event === 'Issue Hook') {\n if (action === 'open' || action === 'reopen') return 'issueOpened';\n if (action === 'close') return 'issueClosed';\n return 'issueUpdated';\n }\n if (parsed.event === 'Note Hook') {\n const noteableType = string(attributes?.noteable_type);\n if (noteableType === 'Issue') return 'issueCommented';\n if (noteableType === 'MergeRequest') return 'mergeRequestCommented';\n return;\n }\n if (parsed.event !== 'Merge Request Hook') return;\n if (action === 'open' || action === 'reopen') return 'mergeRequestOpened';\n if (action === 'merge') return 'mergeRequestMerged';\n if (action === 'close') return 'mergeRequestClosed';\n return 'mergeRequestUpdated';\n}\n\nfunction normalizeHost(host: string): string {\n return host.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nfunction hostFromPayload(parsed: ParsedGitLabWebhook): string | undefined {\n const declaredHost = parsed.instanceHost ? normalizeHost(parsed.instanceHost) : undefined;\n const projectUrl = string(object(parsed.payload.project)?.web_url);\n if (!projectUrl) return declaredHost;\n try {\n const payloadHost = normalizeHost(new URL(projectUrl).host);\n if (declaredHost && declaredHost !== payloadHost) return undefined;\n return payloadHost;\n } catch {\n return undefined;\n }\n}\n\nfunction mergeRequestSourceKey(host: string, projectId: number, mergeRequestIid: number): string {\n return `gitlab-pr:${Buffer.from(JSON.stringify({ version: 1, host, projectId, mergeRequestIid }), 'utf8').toString('base64url')}`;\n}\n\nasync function withRuleTimeout<T>(promise: Promise<T>): Promise<T> {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timeout = setTimeout(() => reject(new Error('FACTORY_RULE_TIMEOUT')), RULE_TIMEOUT_MS);\n }),\n ]);\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\nconst MAX_STALE_RULE_ATTEMPTS = 3;\n\nexport interface GitLabRulesIntegration {\n readonly rules: GitLabEventRules;\n resolveActiveConnectionForHost?(storedConnectionId: string, host: string): Promise<string>;\n getProjectMemberAccessLevel(connectionId: string, projectId: string, username: string): Promise<number | undefined>;\n getWorkItemAuthorUsername(\n connectionId: string,\n projectId: string,\n kind: 'issue' | 'merge_request',\n iid: number,\n ): Promise<string | undefined>;\n}\n\ninterface GitLabRulesOptions {\n gitlab: GitLabRulesIntegration;\n sourceControl: SourceControlStorageHandle;\n projects: FactoryProjectsStorage;\n storage: WorkItemsStorage;\n intake: IntakeStorage;\n configVersion: string;\n boards: BoardRegistry;\n}\n\ninterface ProjectTarget {\n target: ExternalRepositoryProjectTarget;\n connectionIds: string[];\n}\n\nexport class GitLabRules {\n constructor(private readonly options: GitLabRulesOptions) {}\n\n async ingest(parsed: ParsedGitLabWebhook): Promise<{ status: IngressStatus }> {\n const event = eventName(parsed);\n const project = object(parsed.payload.project);\n const projectId = number(project?.id);\n const projectPath = string(project?.path_with_namespace);\n const host = hostFromPayload(parsed);\n const username = string(parsed.payload.user_username) ?? string(object(parsed.payload.user)?.username);\n if (!event || !projectId || !projectPath || !host || !username) return { status: 'ignored' };\n\n const targets = await this.#targets(String(projectId), host);\n if (targets.length === 0) return { status: 'ignored' };\n const results: Array<{ status: IngressStatus }> = [];\n for (const target of targets) {\n results.push(await this.#ingestProject(parsed, event, projectId, projectPath, host, username, target));\n }\n if (results.some(result => result.status === 'committed')) return { status: 'committed' };\n if (results.some(result => result.status === 'replayed')) return { status: 'replayed' };\n return results[0] ?? { status: 'ignored' };\n }\n\n async #targets(repositoryExternalId: string, host: string): Promise<ProjectTarget[]> {\n const grouped = new Map<string, ProjectTarget>();\n const keys = (await this.options.sourceControl.projectRepositories.listConfiguredExternalKeys()).filter(\n key => key.repositoryExternalId === repositoryExternalId,\n );\n for (const key of keys) {\n const targets = await this.options.sourceControl.projectRepositories.listByExternalRepository({\n installationExternalId: key.installationExternalId,\n repositoryExternalId,\n });\n for (const target of targets) {\n const installation = await this.options.sourceControl.installations.findByExternalId({\n orgId: target.orgId,\n externalId: key.installationExternalId,\n });\n const installationHost = string(installation?.providerMetadata.host);\n if (!installationHost || normalizeHost(installationHost) !== normalizeHost(host)) continue;\n const id = `${target.orgId}:${target.factoryProjectId}`;\n const current = grouped.get(id);\n if (current) {\n if (!current.connectionIds.includes(key.installationExternalId)) {\n current.connectionIds.push(key.installationExternalId);\n }\n } else {\n grouped.set(id, { target, connectionIds: [key.installationExternalId] });\n }\n }\n }\n return [...grouped.values()];\n }\n\n async #ingestProject(\n parsed: ParsedGitLabWebhook,\n event: FactoryGitLabEventName,\n projectId: number,\n projectPath: string,\n host: string,\n username: string,\n target: ProjectTarget,\n ): Promise<{ status: IngressStatus }> {\n const factoryProject = await this.options.projects.get({\n orgId: target.target.orgId,\n id: target.target.factoryProjectId,\n });\n if (!factoryProject) return { status: 'missing' };\n\n const sourceId = encodeSourceId({ host, projectId: String(projectId) });\n const config = await this.options.intake.getConfig({\n orgId: target.target.orgId,\n integrationIds: ['gitlab'],\n });\n if (!config.gitlab?.enabled || !config.gitlab.sourceIds?.includes(sourceId)) return { status: 'ignored' };\n const binding = (\n await this.options.intake.listBindings({ orgId: target.target.orgId, integrationId: 'gitlab' })\n ).find(\n candidate => candidate.sourceId === sourceId && candidate.factoryProjectId === target.target.factoryProjectId,\n );\n if (!binding) return { status: 'ignored' };\n const board = this.options.boards.get(binding.board ?? 'work');\n if (!board) return { status: 'ignored' };\n\n const connectionIds = [\n ...new Set(\n await Promise.all(\n target.connectionIds.map(\n connectionId => this.options.gitlab.resolveActiveConnectionForHost?.(connectionId, host) ?? connectionId,\n ),\n ),\n ),\n ];\n\n const attributes = object(parsed.payload.object_attributes);\n const issue = parsed.event === 'Note Hook' ? object(parsed.payload.issue) : attributes;\n const mergeRequest = parsed.event === 'Note Hook' ? object(parsed.payload.merge_request) : attributes;\n const issueIid = number(issue?.iid);\n const mergeRequestIid = number(mergeRequest?.iid);\n const issueSourceKey = issueIid\n ? encodeIssueReference({ host, projectId: String(projectId), issueIid })\n : undefined;\n const mergeRequestKey = mergeRequestIid ? mergeRequestSourceKey(host, projectId, mergeRequestIid) : undefined;\n const items = await this.options.storage.list({\n orgId: target.target.orgId,\n factoryProjectId: target.target.factoryProjectId,\n });\n const issueItem = issueSourceKey\n ? items.find(\n item => item.externalSource?.integrationId === 'gitlab' && item.externalSource.externalId === issueSourceKey,\n )\n : undefined;\n const reviewItem = mergeRequestKey\n ? items.find(\n item => item.externalSource?.integrationId === 'gitlab' && item.externalSource.externalId === mergeRequestKey,\n )\n : undefined;\n const headBranch = string(mergeRequest?.source_branch) ?? '';\n const authoringItem = headBranch\n ? items.find(\n item =>\n item.externalSource?.type !== 'pull-request' &&\n Object.values(item.sessions).some(session => session.branch === headBranch),\n )\n : undefined;\n const actorTrusted = await this.#trusted(connectionIds, String(projectId), username);\n const eventUserId = number(object(parsed.payload.user)?.id) ?? number(parsed.payload.user_id);\n const resolveAuthor = async (\n item: Record<string, unknown> | undefined,\n kind: 'issue' | 'merge_request',\n iid: number | undefined,\n ): Promise<string | undefined> => {\n if (!item || !iid) return undefined;\n const embedded = string(object(item.author)?.username);\n if (embedded) return embedded;\n if (eventUserId && eventUserId === number(item.author_id)) return username;\n for (const connectionId of connectionIds) {\n try {\n const resolved = await this.options.gitlab.getWorkItemAuthorUsername(\n connectionId,\n String(projectId),\n kind,\n iid,\n );\n if (resolved) return resolved;\n } catch {\n // Another active credential may cover this project; otherwise leave author trust unset.\n }\n }\n return undefined;\n };\n const [issueAuthor, mergeRequestAuthor] = await Promise.all([\n resolveAuthor(issue, 'issue', issueIid),\n resolveAuthor(mergeRequest, 'merge_request', mergeRequestIid),\n ]);\n const authorTrusted = async (author: string | undefined): Promise<boolean> => {\n if (!author) return false;\n return author === username ? actorTrusted : this.#trusted(connectionIds, String(projectId), author);\n };\n const [issueAuthorTrusted, mergeRequestAuthorTrusted] = await Promise.all([\n authorTrusted(issueAuthor),\n authorTrusted(mergeRequestAuthor),\n ]);\n const actor: FactoryRuleActor = {\n type: 'gitlab',\n username,\n trusted: actorTrusted,\n factoryAuthored: false,\n };\n\n // A push moves the head a recorded review verdict was given on. Recording\n // the new head lets the verdict badge show that it is outdated, while the\n // verdict itself stays so the next pass still runs as a re-review. It is\n // recorded before the push is evaluated: the dispatcher can apply the\n // re-review transition as soon as it commits, and the pass it starts names\n // the head it covers, which must be the pushed one.\n const lastCommit = object(mergeRequest?.last_commit);\n const headSha = string(lastCommit?.id)?.toLowerCase();\n // Without an update time the commit time still orders the push; dropping\n // the write would leave the pass naming the head the last verdict covered.\n const headAt = timestamp(mergeRequest?.updated_at) ?? timestamp(lastCommit?.timestamp);\n const unchangedListedHead =\n parsed.deliveryId.startsWith('poll:merge-request-head:') &&\n headAt !== undefined &&\n reviewItem?.metadata?.pullRequestHeadSha === headSha &&\n (reviewItem?.metadata?.pullRequestHeadAt !== headAt ||\n reviewItem?.metadata?.pullRequestHeadDeliveryId !== parsed.deliveryId);\n let pushedReviewItem = reviewItem;\n if (event === 'mergeRequestUpdated' && headSha && reviewItem) {\n const parent = items.find(item => item.id === reviewItem.parentWorkItemId);\n // The authoring Work item mirrors the verdict of the merge request it has\n // out; a push to an older one must not mark its successor's verdict.\n await recordPullRequestHead(this.options.storage, {\n orgId: reviewItem.orgId,\n id: reviewItem.id,\n headSha,\n headAt,\n deliveryId: parsed.deliveryId.startsWith('poll:merge-request-head:') ? parsed.deliveryId : undefined,\n });\n if (parent) {\n await recordPullRequestHead(this.options.storage, {\n orgId: parent.orgId,\n id: parent.id,\n headSha,\n headAt,\n ownedPullRequestNumber: mergeRequestIid,\n });\n }\n pushedReviewItem = (await this.options.storage.get({ orgId: reviewItem.orgId, id: reviewItem.id })) ?? reviewItem;\n if (unchangedListedHead) return { status: 'ignored' };\n }\n const candidates: Array<WorkItemRow | undefined> =\n event === 'mergeRequestMerged'\n ? [...new Map([reviewItem, authoringItem].filter(Boolean).map(item => [item!.id, item!])).values()]\n : event === 'mergeRequestCommented'\n ? [authoringItem ?? reviewItem]\n : event === 'mergeRequestOpened'\n ? [authoringItem, ...(authoringItem ? [authoringItem] : [])]\n : event.startsWith('mergeRequest')\n ? [pushedReviewItem ?? authoringItem]\n : [issueItem];\n const results = [];\n for (const [index, item] of candidates.entries()) {\n results.push(\n await this.#evaluate({\n parsed,\n event,\n projectId,\n projectPath,\n host,\n actor,\n orgId: target.target.orgId,\n factoryProjectId: target.target.factoryProjectId,\n factoryProject,\n board: { board: board.id, initialPhase: board.initialPhase },\n issue,\n issueAuthor,\n issueAuthorTrusted,\n issueIid,\n issueSourceKey,\n mergeRequest,\n mergeRequestAuthor,\n mergeRequestAuthorTrusted,\n mergeRequestIid,\n mergeRequestKey,\n factoryAuthored: Boolean(authoringItem),\n item,\n ingressIdentity: `gitlab:${projectId}:${parsed.deliveryId}${index ? `:${item?.id ?? index}` : ''}`,\n // A merge request opening concerns two cards: its own Review card,\n // which the integration handler files against the authoring item,\n // and that authoring item, which its board may react to. The second\n // evaluation runs only the board handler, under an id-suffixed\n // identity so it is not dropped as a replay of the first.\n ...(event === 'mergeRequestOpened' ? { mergeRequestOpenedScope: index ? ('board' as const) : ('intake' as const) } : {}),\n }),\n );\n }\n // The authoring Work item records which merge request it has out, so the\n // Work transition policy keeps an agent from closing the work while it is\n // open. Sessions carry no repository, so a branch shared by two Work cards\n // is ambiguous and records nothing.\n const branchOwners = headBranch\n ? items.filter(\n item =>\n item.externalSource?.type !== 'pull-request' &&\n Object.values(item.sessions).some(session => session.branch === headBranch),\n )\n : [];\n if (authoringItem && mergeRequestIid && branchOwners.length === 1) {\n await this.#trackOpenMergeRequest({\n orgId: authoringItem.orgId,\n id: authoringItem.id,\n event,\n mergeRequestIid,\n eventAt: timestamp(mergeRequest?.updated_at),\n opened: string(mergeRequest?.state) === 'opened' && (actorTrusted || mergeRequestAuthorTrusted),\n headSha: string(object(mergeRequest?.last_commit)?.id)?.toLowerCase(),\n });\n }\n if (results.some(result => result.status === 'committed')) return { status: 'committed' };\n if (results.some(result => result.status === 'replayed')) return { status: 'replayed' };\n return results[0] ?? { status: 'ignored' };\n }\n\n /**\n * Records or clears the merge request a Work card has out. Each merge\n * request's last applied event time is kept on the card, so an opening that\n * is older than a close already applied (a replay, or a close delivered\n * first) is ignored, while a genuine reopen is newer and records it again.\n */\n async #trackOpenMergeRequest(input: {\n orgId: string;\n id: string;\n event: string;\n mergeRequestIid: number;\n eventAt: number | undefined;\n opened: boolean;\n headSha: string | undefined;\n }): Promise<void> {\n const settling = input.event === 'mergeRequestMerged' || input.event === 'mergeRequestClosed';\n if (input.event !== 'mergeRequestOpened' && !settling) return;\n const key = String(input.mergeRequestIid);\n for (let attempt = 0; attempt < 3; attempt++) {\n const item = await this.options.storage.get({ orgId: input.orgId, id: input.id });\n if (!item) return;\n const events = object(item.metadata?.mergeRequestEvents) ?? {};\n const last = object(events[key]);\n const lastAt = number(last?.at);\n if (input.eventAt !== undefined && lastAt !== undefined && lastAt >= input.eventAt) return;\n // Without a timestamp, only an opening that no close has settled is trusted.\n if (input.eventAt === undefined && !settling && last?.open === false) return;\n if (!settling && !input.opened) return;\n const recorded = item.metadata?.openPullRequestNumber;\n const patch: Record<string, unknown> = {\n mergeRequestEvents: { ...events, [key]: { at: input.eventAt ?? lastAt ?? null, open: !settling } },\n };\n if (!settling) {\n // A head recorded for an earlier merge request must not mark this one's\n // verdict outdated. A replayed opening of the merge request already\n // recorded keeps the head its pushes left.\n if (recorded !== input.mergeRequestIid) {\n patch.pullRequestHeadSha = input.headSha ?? null;\n patch.pullRequestHeadAt = input.eventAt ?? null;\n }\n patch.openPullRequestNumber = input.mergeRequestIid;\n } else if (recorded === input.mergeRequestIid) {\n patch.openPullRequestNumber = null;\n if (input.event === 'mergeRequestMerged' && typeof item.metadata?.reviewVerdict === 'string') {\n patch.reviewVerdict = null;\n }\n }\n try {\n await this.options.storage.update({\n orgId: item.orgId,\n id: item.id,\n userId: 'factory-rule-dispatcher',\n expectedRevision: item.revision,\n patch: { metadata: patch },\n });\n return;\n } catch (error) {\n if (!(error instanceof WorkItemUpdateConflictError)) throw error;\n }\n }\n }\n\n async #trusted(connectionIds: string[], projectId: string, username: string): Promise<boolean> {\n for (const connectionId of connectionIds) {\n try {\n const level = await this.options.gitlab.getProjectMemberAccessLevel(connectionId, projectId, username);\n if (level !== undefined) return level >= GITLAB_TRUSTED_ACCESS_LEVEL;\n } catch {\n // Try another active credential covering the same canonical project; otherwise fail closed.\n }\n }\n return false;\n }\n\n async #evaluate(\n input: {\n parsed: ParsedGitLabWebhook;\n event: FactoryGitLabEventName;\n projectId: number;\n projectPath: string;\n host: string;\n actor: FactoryRuleActor;\n orgId: string;\n factoryProjectId: string;\n factoryProject: { createdAt: Date };\n board: { board: string; initialPhase: string };\n issue: Record<string, unknown> | undefined;\n issueAuthor: string | undefined;\n issueAuthorTrusted: boolean;\n issueIid: number | undefined;\n issueSourceKey: string | undefined;\n mergeRequest: Record<string, unknown> | undefined;\n mergeRequestAuthor: string | undefined;\n mergeRequestAuthorTrusted: boolean;\n mergeRequestIid: number | undefined;\n mergeRequestKey: string | undefined;\n factoryAuthored: boolean;\n item: WorkItemRow | undefined;\n ingressIdentity: string;\n mergeRequestOpenedScope?: 'intake' | 'board';\n },\n attempt = 1,\n ): Promise<{ status: IngressStatus }> {\n const note = object(input.parsed.payload.object_attributes);\n const issueAuthor = input.issueAuthor;\n const mergeRequestAuthor = input.mergeRequestAuthor;\n const mergeRequestState = string(input.mergeRequest?.state);\n const context: FactoryGitLabRuleContext = {\n tenant: { orgId: input.orgId, projectId: input.factoryProjectId },\n actor: input.actor,\n ingress: { type: 'gitlab', id: input.ingressIdentity },\n cause: `gitlab.${input.event}`,\n causalChain: [],\n configVersion: this.options.configVersion,\n ...(input.item\n ? {\n item: {\n id: input.item.id,\n source:\n input.item.externalSource?.type === 'pull-request'\n ? ('gitlab-pr' as const)\n : input.item.externalSource?.integrationId === 'gitlab'\n ? ('gitlab-issue' as const)\n : ('manual' as const),\n sourceKey: input.item.externalSource?.externalId ?? null,\n parentWorkItemId: input.item.parentWorkItemId,\n title: input.item.title,\n url: input.item.externalSource?.url ?? null,\n stages: input.item.stages,\n acceptedAt: input.item.acceptedAt,\n metadata: input.item.metadata,\n },\n board: boardForWorkItem(input.item),\n itemRevision: input.item.revision,\n ...withBoardClosure(this.options.boards, input.item),\n ...rulePhaseField(this.options.boards, input.item),\n }\n : {}),\n intake: input.board,\n event: input.event,\n deliveryId: input.parsed.deliveryId,\n factory: { createdAt: input.factoryProject.createdAt.toISOString() },\n repository: { id: input.projectId, fullName: input.projectPath, host: input.host },\n ...(input.issueIid && input.issueSourceKey && string(input.issue?.title)\n ? {\n issue: {\n number: input.issueIid,\n sourceKey: input.issueSourceKey,\n title: string(input.issue?.title)!,\n url:\n string(input.issue?.url) ??\n string(input.issue?.web_url) ??\n `https://${input.host}/${input.projectPath}/-/issues/${input.issueIid}`,\n ...(string(input.issue?.created_at) ? { createdAt: string(input.issue?.created_at) } : {}),\n ...(string(input.issue?.updated_at) ? { updatedAt: string(input.issue?.updated_at) } : {}),\n assignees: usernames(input.parsed.payload.assignees ?? input.issue?.assignees),\n labels: labelNames(input.issue?.labels ?? input.parsed.payload.labels),\n labelColors: labelColors(input.issue?.labels ?? input.parsed.payload.labels),\n state: string(input.issue?.state) === 'closed' ? ('closed' as const) : ('open' as const),\n ...(issueAuthor ? { author: issueAuthor } : {}),\n authorTrusted: input.issueAuthorTrusted,\n },\n }\n : {}),\n ...(input.parsed.event === 'Note Hook' && number(note?.id)\n ? {\n note: {\n id: number(note?.id)!,\n ...(string(note?.note) ? { body: string(note?.note) } : {}),\n ...(string(note?.url) ? { url: string(note?.url) } : {}),\n ...(string(object(input.parsed.payload.user)?.username)\n ? { author: string(object(input.parsed.payload.user)?.username) }\n : {}),\n ...(string(note?.created_at) ? { createdAt: string(note?.created_at) } : {}),\n ...(string(note?.updated_at) ? { updatedAt: string(note?.updated_at) } : {}),\n },\n }\n : {}),\n ...(input.mergeRequestIid && input.mergeRequestKey && string(input.mergeRequest?.title)\n ? {\n mergeRequest: {\n number: input.mergeRequestIid,\n sourceKey: input.mergeRequestKey,\n title: string(input.mergeRequest?.title)!,\n url:\n string(input.mergeRequest?.url) ??\n string(input.mergeRequest?.web_url) ??\n `https://${input.host}/${input.projectPath}/-/merge_requests/${input.mergeRequestIid}`,\n ...(string(input.mergeRequest?.created_at) ? { createdAt: string(input.mergeRequest?.created_at) } : {}),\n state:\n mergeRequestState === 'closed' || mergeRequestState === 'merged'\n ? ('closed' as const)\n : ('open' as const),\n draft: boolean(input.mergeRequest?.draft) ?? boolean(input.mergeRequest?.work_in_progress) ?? false,\n merged: input.event === 'mergeRequestMerged' || mergeRequestState === 'merged',\n assignees: usernames(input.parsed.payload.assignees ?? input.mergeRequest?.assignees),\n reviewers: usernames(input.parsed.payload.reviewers ?? input.mergeRequest?.reviewers),\n labels: labelNames(input.mergeRequest?.labels ?? input.parsed.payload.labels),\n labelColors: labelColors(input.mergeRequest?.labels ?? input.parsed.payload.labels),\n ...(mergeRequestAuthor ? { author: mergeRequestAuthor } : {}),\n authorTrusted: input.mergeRequestAuthorTrusted,\n factoryAuthored: input.factoryAuthored,\n headBranch: string(input.mergeRequest?.source_branch) ?? '',\n baseBranch: string(input.mergeRequest?.target_branch) ?? '',\n },\n }\n : {}),\n };\n const boardRules = boardEventHandlers(\n this.options.boards,\n input.mergeRequestOpenedScope === 'intake' ? undefined : eventBoardId(context),\n 'gitlab',\n );\n const rule =\n input.mergeRequestOpenedScope === 'board'\n ? hasExplicitRuleOverride(this.options.gitlab.rules, input.event)\n ? undefined\n : boardRules?.mergeRequestOpened\n : selectEventRule(this.options.gitlab.rules, boardRules, input.event);\n // Without a board handler the authoring card has nothing to answer; skip\n // recording an empty evaluation for it.\n if (input.mergeRequestOpenedScope === 'board' && !rule) return { status: 'ignored' };\n let decision: FactoryRuleDecision | void;\n let decisions: Record<string, unknown>[] = [];\n let outcome: { status: 'accepted' | 'rejected'; code?: string; reason?: string } = { status: 'accepted' };\n try {\n decision = rule ? await withRuleTimeout(Promise.resolve(rule(Object.freeze(context)))) : undefined;\n if (decision?.type === 'reject') {\n outcome = { status: 'rejected', code: decision.code, reason: decision.reason };\n } else if (decision) {\n decisions = validateFactoryRuleDecisions([decision]).map(entry => {\n assertFactoryDecisionTarget(\n entry,\n this.options.boards,\n input.item ? boardForWorkItem(input.item) : undefined,\n );\n return { ...entry };\n });\n }\n } catch (error) {\n const timedOut = error instanceof Error && error.message === 'FACTORY_RULE_TIMEOUT';\n outcome = {\n status: 'rejected',\n code: timedOut ? 'timeout' : 'rule_error',\n reason: timedOut\n ? 'Factory rule evaluation timed out.'\n : error instanceof Error\n ? error.message.slice(0, 2_000)\n : 'Factory GitLab rule failed.',\n };\n }\n\n const committed = await this.options.storage.commitRuleEvaluation({\n orgId: input.orgId,\n factoryProjectId: input.factoryProjectId,\n workItemId: input.item?.id ?? null,\n ingress: { identity: input.ingressIdentity, triggerType: `gitlab.${input.event}` },\n configVersion: this.options.configVersion,\n expectedRevision: input.item?.revision ?? null,\n actor: { ...input.actor },\n outcome,\n decisions,\n causalChain: [],\n now: new Date(),\n });\n if (committed.status === 'stale') {\n // Nothing was persisted: re-read the item and evaluate again at its fresh revision.\n if (attempt >= MAX_STALE_RULE_ATTEMPTS) {\n throw new Error(`Factory GitLab rule evaluation for ${input.ingressIdentity} kept losing revision races.`);\n }\n const fresh = input.item ? await this.options.storage.get({ orgId: input.orgId, id: input.item.id }) : null;\n if (input.item && !fresh) return { status: 'missing' };\n return this.#evaluate({ ...input, item: fresh ?? undefined }, attempt + 1);\n }\n return { status: committed.status };\n }\n}\n\nexport function attachGitLabRules(\n gitlab: GitLabRulesIntegration,\n context: IntegrationContext,\n): ((event: ParsedGitLabWebhook) => Promise<unknown>) | undefined {\n if (!context.runtime) return undefined;\n const rules = new GitLabRules({\n gitlab,\n sourceControl: context.storage.sourceControl,\n projects: context.storage.projects,\n storage: context.runtime.workItems,\n intake: context.storage.intake,\n configVersion: context.runtime.configVersion,\n boards: context.runtime.boards,\n });\n return event => rules.ingest(event);\n}\n"],"mappings":";;;;;;;;AA8BA,MAAM,kBAAkB;AAIxB,SAAS,OAAO,OAAqD;CACnE,OAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAK,QAAoC,KAAA;AAC5G;AAEA,SAAS,OAAO,OAAoC;CAClD,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ,KAAA;AACjE;AAEA,SAAS,OAAO,OAAoC;CAClD,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ,KAAA;AACvE;;AAGA,SAAS,UAAU,OAAoC;CACrD,MAAM,OAAO,OAAO,KAAK;CACzB,IAAI,CAAC,MAAM,OAAO,KAAA;CAClB,MAAM,SAAS,mFAAmF,KAAK,IAAI;CAC3G,MAAM,SAAS,KAAK,MAClB,SAAS,GAAG,OAAO,GAAG,GAAG,OAAO,KAAK,OAAO,KAAK,GAAG,OAAO,GAAG,GAAG,OAAO,OAAO,QAAQ,IACzF;CACA,OAAO,OAAO,MAAM,MAAM,IAAI,KAAA,IAAY;AAC5C;AAEA,SAAS,QAAQ,OAAqC;CACpD,OAAO,OAAO,UAAU,YAAY,QAAQ,KAAA;AAC9C;AAEA,SAAS,UAAU,OAA0B;CAC3C,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC;CACnC,OAAO,MAAM,SAAQ,UAAS;EAC5B,MAAM,WAAW,OAAO,OAAO,KAAK,CAAC,EAAE,QAAQ;EAC/C,OAAO,WAAW,CAAC,QAAQ,IAAI,CAAC;CAClC,CAAC;AACH;AAEA,SAAS,WAAW,OAA0B;CAC5C,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC;CACnC,OAAO,MAAM,SAAQ,UAAS;EAC5B,IAAI,OAAO,UAAU,UAAU,OAAO,QAAQ,CAAC,KAAK,IAAI,CAAC;EACzD,MAAM,QAAQ,OAAO,OAAO,KAAK,CAAC,EAAE,KAAK,KAAK,OAAO,OAAO,KAAK,CAAC,EAAE,IAAI;EACxE,OAAO,QAAQ,CAAC,KAAK,IAAI,CAAC;CAC5B,CAAC;AACH;AAEA,SAAS,YAAY,OAAwC;CAC3D,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC;CACnC,OAAO,OAAO,YACZ,MAAM,SAAQ,UAAS;EACrB,MAAM,QAAQ,OAAO,KAAK;EAC1B,MAAM,OAAO,OAAO,OAAO,KAAK,KAAK,OAAO,OAAO,IAAI;EACvD,MAAM,QAAQ,OAAO,OAAO,KAAK;EACjC,OAAO,QAAQ,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC;CAC5C,CAAC,CACH;AACF;AAEA,SAAS,UAAU,QAAiE;CAClF,MAAM,aAAa,OAAO,OAAO,QAAQ,iBAAiB;CAC1D,MAAM,SAAS,OAAO,YAAY,MAAM,CAAC,EAAE,YAAY;CACvD,IAAI,OAAO,UAAU,cAAc;EACjC,IAAI,WAAW,UAAU,WAAW,UAAU,OAAO;EACrD,IAAI,WAAW,SAAS,OAAO;EAC/B,OAAO;CACT;CACA,IAAI,OAAO,UAAU,aAAa;EAChC,MAAM,eAAe,OAAO,YAAY,aAAa;EACrD,IAAI,iBAAiB,SAAS,OAAO;EACrC,IAAI,iBAAiB,gBAAgB,OAAO;EAC5C;CACF;CACA,IAAI,OAAO,UAAU,sBAAsB;CAC3C,IAAI,WAAW,UAAU,WAAW,UAAU,OAAO;CACrD,IAAI,WAAW,SAAS,OAAO;CAC/B,IAAI,WAAW,SAAS,OAAO;CAC/B,OAAO;AACT;AAEA,SAAS,cAAc,MAAsB;CAC3C,OAAO,KAAK,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,OAAO,EAAE;AACpD;AAEA,SAAS,gBAAgB,QAAiD;CACxE,MAAM,eAAe,OAAO,eAAe,cAAc,OAAO,YAAY,IAAI,KAAA;CAChF,MAAM,aAAa,OAAO,OAAO,OAAO,QAAQ,OAAO,CAAC,EAAE,OAAO;CACjE,IAAI,CAAC,YAAY,OAAO;CACxB,IAAI;EACF,MAAM,cAAc,cAAc,IAAI,IAAI,UAAU,CAAC,CAAC,IAAI;EAC1D,IAAI,gBAAgB,iBAAiB,aAAa,OAAO,KAAA;EACzD,OAAO;CACT,QAAQ;EACN;CACF;AACF;AAEA,SAAS,sBAAsB,MAAc,WAAmB,iBAAiC;CAC/F,OAAO,aAAa,OAAO,KAAK,KAAK,UAAU;EAAE,SAAS;EAAG;EAAM;EAAW;CAAgB,CAAC,GAAG,MAAM,CAAC,CAAC,SAAS,WAAW;AAChI;AAEA,eAAe,gBAAmB,SAAiC;CACjE,IAAI;CACJ,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CACxB,SACA,IAAI,SAAgB,GAAG,WAAW;GAChC,UAAU,iBAAiB,uBAAO,IAAI,MAAM,sBAAsB,CAAC,GAAG,eAAe;EACvF,CAAC,CACH,CAAC;CACH,UAAU;EACR,IAAI,SAAS,aAAa,OAAO;CACnC;AACF;AAEA,MAAM,0BAA0B;AA6BhC,IAAa,cAAb,MAAyB;CACM;CAA7B,YAAY,SAA8C;EAA7B,KAAA,UAAA;CAA8B;CAE3D,MAAM,OAAO,QAAiE;EAC5E,MAAM,QAAQ,UAAU,MAAM;EAC9B,MAAM,UAAU,OAAO,OAAO,QAAQ,OAAO;EAC7C,MAAM,YAAY,OAAO,SAAS,EAAE;EACpC,MAAM,cAAc,OAAO,SAAS,mBAAmB;EACvD,MAAM,OAAO,gBAAgB,MAAM;EACnC,MAAM,WAAW,OAAO,OAAO,QAAQ,aAAa,KAAK,OAAO,OAAO,OAAO,QAAQ,IAAI,CAAC,EAAE,QAAQ;EACrG,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,eAAe,CAAC,QAAQ,CAAC,UAAU,OAAO,EAAE,QAAQ,UAAU;EAE3F,MAAM,UAAU,MAAM,KAAK,SAAS,OAAO,SAAS,GAAG,IAAI;EAC3D,IAAI,QAAQ,WAAW,GAAG,OAAO,EAAE,QAAQ,UAAU;EACrD,MAAM,UAA4C,CAAC;EACnD,KAAK,MAAM,UAAU,SACnB,QAAQ,KAAK,MAAM,KAAK,eAAe,QAAQ,OAAO,WAAW,aAAa,MAAM,UAAU,MAAM,CAAC;EAEvG,IAAI,QAAQ,MAAK,WAAU,OAAO,WAAW,WAAW,GAAG,OAAO,EAAE,QAAQ,YAAY;EACxF,IAAI,QAAQ,MAAK,WAAU,OAAO,WAAW,UAAU,GAAG,OAAO,EAAE,QAAQ,WAAW;EACtF,OAAO,QAAQ,MAAM,EAAE,QAAQ,UAAU;CAC3C;CAEA,MAAM,SAAS,sBAA8B,MAAwC;EACnF,MAAM,0BAAU,IAAI,IAA2B;EAC/C,MAAM,QAAQ,MAAM,KAAK,QAAQ,cAAc,oBAAoB,2BAA2B,EAAA,CAAG,QAC/F,QAAO,IAAI,yBAAyB,oBACtC;EACA,KAAK,MAAM,OAAO,MAAM;GACtB,MAAM,UAAU,MAAM,KAAK,QAAQ,cAAc,oBAAoB,yBAAyB;IAC5F,wBAAwB,IAAI;IAC5B;GACF,CAAC;GACD,KAAK,MAAM,UAAU,SAAS;IAK5B,MAAM,mBAAmB,QAAO,MAJL,KAAK,QAAQ,cAAc,cAAc,iBAAiB;KACnF,OAAO,OAAO;KACd,YAAY,IAAI;IAClB,CAAC,EAAA,EAC6C,iBAAiB,IAAI;IACnE,IAAI,CAAC,oBAAoB,cAAc,gBAAgB,MAAM,cAAc,IAAI,GAAG;IAClF,MAAM,KAAK,GAAG,OAAO,MAAM,GAAG,OAAO;IACrC,MAAM,UAAU,QAAQ,IAAI,EAAE;IAC9B,IAAI,SACE;SAAA,CAAC,QAAQ,cAAc,SAAS,IAAI,sBAAsB,GAC5D,QAAQ,cAAc,KAAK,IAAI,sBAAsB;IAAA,OAGvD,QAAQ,IAAI,IAAI;KAAE;KAAQ,eAAe,CAAC,IAAI,sBAAsB;IAAE,CAAC;GAE3E;EACF;EACA,OAAO,CAAC,GAAG,QAAQ,OAAO,CAAC;CAC7B;CAEA,MAAM,eACJ,QACA,OACA,WACA,aACA,MACA,UACA,QACoC;EACpC,MAAM,iBAAiB,MAAM,KAAK,QAAQ,SAAS,IAAI;GACrD,OAAO,OAAO,OAAO;GACrB,IAAI,OAAO,OAAO;EACpB,CAAC;EACD,IAAI,CAAC,gBAAgB,OAAO,EAAE,QAAQ,UAAU;EAEhD,MAAM,WAAW,eAAe;GAAE;GAAM,WAAW,OAAO,SAAS;EAAE,CAAC;EACtE,MAAM,SAAS,MAAM,KAAK,QAAQ,OAAO,UAAU;GACjD,OAAO,OAAO,OAAO;GACrB,gBAAgB,CAAC,QAAQ;EAC3B,CAAC;EACD,IAAI,CAAC,OAAO,QAAQ,WAAW,CAAC,OAAO,OAAO,WAAW,SAAS,QAAQ,GAAG,OAAO,EAAE,QAAQ,UAAU;EACxG,MAAM,WACJ,MAAM,KAAK,QAAQ,OAAO,aAAa;GAAE,OAAO,OAAO,OAAO;GAAO,eAAe;EAAS,CAAC,EAAA,CAC9F,MACA,cAAa,UAAU,aAAa,YAAY,UAAU,qBAAqB,OAAO,OAAO,gBAC/F;EACA,IAAI,CAAC,SAAS,OAAO,EAAE,QAAQ,UAAU;EACzC,MAAM,QAAQ,KAAK,QAAQ,OAAO,IAAI,QAAQ,SAAS,MAAM;EAC7D,IAAI,CAAC,OAAO,OAAO,EAAE,QAAQ,UAAU;EAEvC,MAAM,gBAAgB,CACpB,GAAG,IAAI,IACL,MAAM,QAAQ,IACZ,OAAO,cAAc,KACnB,iBAAgB,KAAK,QAAQ,OAAO,iCAAiC,cAAc,IAAI,KAAK,YAC9F,CACF,CACF,CACF;EAEA,MAAM,aAAa,OAAO,OAAO,QAAQ,iBAAiB;EAC1D,MAAM,QAAQ,OAAO,UAAU,cAAc,OAAO,OAAO,QAAQ,KAAK,IAAI;EAC5E,MAAM,eAAe,OAAO,UAAU,cAAc,OAAO,OAAO,QAAQ,aAAa,IAAI;EAC3F,MAAM,WAAW,OAAO,OAAO,GAAG;EAClC,MAAM,kBAAkB,OAAO,cAAc,GAAG;EAChD,MAAM,iBAAiB,WACnB,qBAAqB;GAAE;GAAM,WAAW,OAAO,SAAS;GAAG;EAAS,CAAC,IACrE,KAAA;EACJ,MAAM,kBAAkB,kBAAkB,sBAAsB,MAAM,WAAW,eAAe,IAAI,KAAA;EACpG,MAAM,QAAQ,MAAM,KAAK,QAAQ,QAAQ,KAAK;GAC5C,OAAO,OAAO,OAAO;GACrB,kBAAkB,OAAO,OAAO;EAClC,CAAC;EACD,MAAM,YAAY,iBACd,MAAM,MACJ,SAAQ,KAAK,gBAAgB,kBAAkB,YAAY,KAAK,eAAe,eAAe,cAChG,IACA,KAAA;EACJ,MAAM,aAAa,kBACf,MAAM,MACJ,SAAQ,KAAK,gBAAgB,kBAAkB,YAAY,KAAK,eAAe,eAAe,eAChG,IACA,KAAA;EACJ,MAAM,aAAa,OAAO,cAAc,aAAa,KAAK;EAC1D,MAAM,gBAAgB,aAClB,MAAM,MACJ,SACE,KAAK,gBAAgB,SAAS,kBAC9B,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,MAAK,YAAW,QAAQ,WAAW,UAAU,CAC9E,IACA,KAAA;EACJ,MAAM,eAAe,MAAM,KAAK,SAAS,eAAe,OAAO,SAAS,GAAG,QAAQ;EACnF,MAAM,cAAc,OAAO,OAAO,OAAO,QAAQ,IAAI,CAAC,EAAE,EAAE,KAAK,OAAO,OAAO,QAAQ,OAAO;EAC5F,MAAM,gBAAgB,OACpB,MACA,MACA,QACgC;GAChC,IAAI,CAAC,QAAQ,CAAC,KAAK,OAAO,KAAA;GAC1B,MAAM,WAAW,OAAO,OAAO,KAAK,MAAM,CAAC,EAAE,QAAQ;GACrD,IAAI,UAAU,OAAO;GACrB,IAAI,eAAe,gBAAgB,OAAO,KAAK,SAAS,GAAG,OAAO;GAClE,KAAK,MAAM,gBAAgB,eACzB,IAAI;IACF,MAAM,WAAW,MAAM,KAAK,QAAQ,OAAO,0BACzC,cACA,OAAO,SAAS,GAChB,MACA,GACF;IACA,IAAI,UAAU,OAAO;GACvB,QAAQ,CAER;EAGJ;EACA,MAAM,CAAC,aAAa,sBAAsB,MAAM,QAAQ,IAAI,CAC1D,cAAc,OAAO,SAAS,QAAQ,GACtC,cAAc,cAAc,iBAAiB,eAAe,CAC9D,CAAC;EACD,MAAM,gBAAgB,OAAO,WAAiD;GAC5E,IAAI,CAAC,QAAQ,OAAO;GACpB,OAAO,WAAW,WAAW,eAAe,KAAK,SAAS,eAAe,OAAO,SAAS,GAAG,MAAM;EACpG;EACA,MAAM,CAAC,oBAAoB,6BAA6B,MAAM,QAAQ,IAAI,CACxE,cAAc,WAAW,GACzB,cAAc,kBAAkB,CAClC,CAAC;EACD,MAAM,QAA0B;GAC9B,MAAM;GACN;GACA,SAAS;GACT,iBAAiB;EACnB;EAQA,MAAM,aAAa,OAAO,cAAc,WAAW;EACnD,MAAM,UAAU,OAAO,YAAY,EAAE,CAAC,EAAE,YAAY;EAGpD,MAAM,SAAS,UAAU,cAAc,UAAU,KAAK,UAAU,YAAY,SAAS;EACrF,MAAM,sBACJ,OAAO,WAAW,WAAW,0BAA0B,KACvD,WAAW,KAAA,KACX,YAAY,UAAU,uBAAuB,YAC5C,YAAY,UAAU,sBAAsB,UAC3C,YAAY,UAAU,8BAA8B,OAAO;EAC/D,IAAI,mBAAmB;EACvB,IAAI,UAAU,yBAAyB,WAAW,YAAY;GAC5D,MAAM,SAAS,MAAM,MAAK,SAAQ,KAAK,OAAO,WAAW,gBAAgB;GAGzE,MAAM,sBAAsB,KAAK,QAAQ,SAAS;IAChD,OAAO,WAAW;IAClB,IAAI,WAAW;IACf;IACA;IACA,YAAY,OAAO,WAAW,WAAW,0BAA0B,IAAI,OAAO,aAAa,KAAA;GAC7F,CAAC;GACD,IAAI,QACF,MAAM,sBAAsB,KAAK,QAAQ,SAAS;IAChD,OAAO,OAAO;IACd,IAAI,OAAO;IACX;IACA;IACA,wBAAwB;GAC1B,CAAC;GAEH,mBAAoB,MAAM,KAAK,QAAQ,QAAQ,IAAI;IAAE,OAAO,WAAW;IAAO,IAAI,WAAW;GAAG,CAAC,KAAM;GACvG,IAAI,qBAAqB,OAAO,EAAE,QAAQ,UAAU;EACtD;EACA,MAAM,aACJ,UAAU,uBACN,CAAC,GAAG,IAAI,IAAI,CAAC,YAAY,aAAa,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAI,SAAQ,CAAC,KAAM,IAAI,IAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAChG,UAAU,0BACR,CAAC,iBAAiB,UAAU,IAC5B,UAAU,uBACR,CAAC,eAAe,GAAI,gBAAgB,CAAC,aAAa,IAAI,CAAC,CAAE,IACzD,MAAM,WAAW,cAAc,IAC7B,CAAC,oBAAoB,aAAa,IAClC,CAAC,SAAS;EACtB,MAAM,UAAU,CAAC;EACjB,KAAK,MAAM,CAAC,OAAO,SAAS,WAAW,QAAQ,GAC7C,QAAQ,KACN,MAAM,KAAK,UAAU;GACnB;GACA;GACA;GACA;GACA;GACA;GACA,OAAO,OAAO,OAAO;GACrB,kBAAkB,OAAO,OAAO;GAChC;GACA,OAAO;IAAE,OAAO,MAAM;IAAI,cAAc,MAAM;GAAa;GAC3D;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,iBAAiB,QAAQ,aAAa;GACtC;GACA,iBAAiB,UAAU,UAAU,GAAG,OAAO,aAAa,QAAQ,IAAI,MAAM,MAAM,UAAU;GAM9F,GAAI,UAAU,uBAAuB,EAAE,yBAAyB,QAAS,UAAqB,SAAmB,IAAI,CAAC;EACxH,CAAC,CACH;EAMF,MAAM,eAAe,aACjB,MAAM,QACJ,SACE,KAAK,gBAAgB,SAAS,kBAC9B,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,MAAK,YAAW,QAAQ,WAAW,UAAU,CAC9E,IACA,CAAC;EACL,IAAI,iBAAiB,mBAAmB,aAAa,WAAW,GAC9D,MAAM,KAAK,uBAAuB;GAChC,OAAO,cAAc;GACrB,IAAI,cAAc;GAClB;GACA;GACA,SAAS,UAAU,cAAc,UAAU;GAC3C,QAAQ,OAAO,cAAc,KAAK,MAAM,aAAa,gBAAgB;GACrE,SAAS,OAAO,OAAO,cAAc,WAAW,CAAC,EAAE,EAAE,CAAC,EAAE,YAAY;EACtE,CAAC;EAEH,IAAI,QAAQ,MAAK,WAAU,OAAO,WAAW,WAAW,GAAG,OAAO,EAAE,QAAQ,YAAY;EACxF,IAAI,QAAQ,MAAK,WAAU,OAAO,WAAW,UAAU,GAAG,OAAO,EAAE,QAAQ,WAAW;EACtF,OAAO,QAAQ,MAAM,EAAE,QAAQ,UAAU;CAC3C;;;;;;;CAQA,MAAM,uBAAuB,OAQX;EAChB,MAAM,WAAW,MAAM,UAAU,wBAAwB,MAAM,UAAU;EACzE,IAAI,MAAM,UAAU,wBAAwB,CAAC,UAAU;EACvD,MAAM,MAAM,OAAO,MAAM,eAAe;EACxC,KAAK,IAAI,UAAU,GAAG,UAAU,GAAG,WAAW;GAC5C,MAAM,OAAO,MAAM,KAAK,QAAQ,QAAQ,IAAI;IAAE,OAAO,MAAM;IAAO,IAAI,MAAM;GAAG,CAAC;GAChF,IAAI,CAAC,MAAM;GACX,MAAM,SAAS,OAAO,KAAK,UAAU,kBAAkB,KAAK,CAAC;GAC7D,MAAM,OAAO,OAAO,OAAO,IAAI;GAC/B,MAAM,SAAS,OAAO,MAAM,EAAE;GAC9B,IAAI,MAAM,YAAY,KAAA,KAAa,WAAW,KAAA,KAAa,UAAU,MAAM,SAAS;GAEpF,IAAI,MAAM,YAAY,KAAA,KAAa,CAAC,YAAY,MAAM,SAAS,OAAO;GACtE,IAAI,CAAC,YAAY,CAAC,MAAM,QAAQ;GAChC,MAAM,WAAW,KAAK,UAAU;GAChC,MAAM,QAAiC,EACrC,oBAAoB;IAAE,GAAG;KAAS,MAAM;KAAE,IAAI,MAAM,WAAW,UAAU;KAAM,MAAM,CAAC;IAAS;GAAE,EACnG;GACA,IAAI,CAAC,UAAU;IAIb,IAAI,aAAa,MAAM,iBAAiB;KACtC,MAAM,qBAAqB,MAAM,WAAW;KAC5C,MAAM,oBAAoB,MAAM,WAAW;IAC7C;IACA,MAAM,wBAAwB,MAAM;GACtC,OAAO,IAAI,aAAa,MAAM,iBAAiB;IAC7C,MAAM,wBAAwB;IAC9B,IAAI,MAAM,UAAU,wBAAwB,OAAO,KAAK,UAAU,kBAAkB,UAClF,MAAM,gBAAgB;GAE1B;GACA,IAAI;IACF,MAAM,KAAK,QAAQ,QAAQ,OAAO;KAChC,OAAO,KAAK;KACZ,IAAI,KAAK;KACT,QAAQ;KACR,kBAAkB,KAAK;KACvB,OAAO,EAAE,UAAU,MAAM;IAC3B,CAAC;IACD;GACF,SAAS,OAAO;IACd,IAAI,EAAE,iBAAiB,8BAA8B,MAAM;GAC7D;EACF;CACF;CAEA,MAAM,SAAS,eAAyB,WAAmB,UAAoC;EAC7F,KAAK,MAAM,gBAAgB,eACzB,IAAI;GACF,MAAM,QAAQ,MAAM,KAAK,QAAQ,OAAO,4BAA4B,cAAc,WAAW,QAAQ;GACrG,IAAI,UAAU,KAAA,GAAW,OAAO,SAAA;EAClC,QAAQ,CAER;EAEF,OAAO;CACT;CAEA,MAAM,UACJ,OA0BA,UAAU,GAC0B;EACpC,MAAM,OAAO,OAAO,MAAM,OAAO,QAAQ,iBAAiB;EAC1D,MAAM,cAAc,MAAM;EAC1B,MAAM,qBAAqB,MAAM;EACjC,MAAM,oBAAoB,OAAO,MAAM,cAAc,KAAK;EAC1D,MAAM,UAAoC;GACxC,QAAQ;IAAE,OAAO,MAAM;IAAO,WAAW,MAAM;GAAiB;GAChE,OAAO,MAAM;GACb,SAAS;IAAE,MAAM;IAAU,IAAI,MAAM;GAAgB;GACrD,OAAO,UAAU,MAAM;GACvB,aAAa,CAAC;GACd,eAAe,KAAK,QAAQ;GAC5B,GAAI,MAAM,OACN;IACE,MAAM;KACJ,IAAI,MAAM,KAAK;KACf,QACE,MAAM,KAAK,gBAAgB,SAAS,iBAC/B,cACD,MAAM,KAAK,gBAAgB,kBAAkB,WAC1C,iBACA;KACT,WAAW,MAAM,KAAK,gBAAgB,cAAc;KACpD,kBAAkB,MAAM,KAAK;KAC7B,OAAO,MAAM,KAAK;KAClB,KAAK,MAAM,KAAK,gBAAgB,OAAO;KACvC,QAAQ,MAAM,KAAK;KACnB,YAAY,MAAM,KAAK;KACvB,UAAU,MAAM,KAAK;IACvB;IACA,OAAO,iBAAiB,MAAM,IAAI;IAClC,cAAc,MAAM,KAAK;IACzB,GAAG,iBAAiB,KAAK,QAAQ,QAAQ,MAAM,IAAI;IACnD,GAAG,eAAe,KAAK,QAAQ,QAAQ,MAAM,IAAI;GACnD,IACA,CAAC;GACL,QAAQ,MAAM;GACd,OAAO,MAAM;GACb,YAAY,MAAM,OAAO;GACzB,SAAS,EAAE,WAAW,MAAM,eAAe,UAAU,YAAY,EAAE;GACnE,YAAY;IAAE,IAAI,MAAM;IAAW,UAAU,MAAM;IAAa,MAAM,MAAM;GAAK;GACjF,GAAI,MAAM,YAAY,MAAM,kBAAkB,OAAO,MAAM,OAAO,KAAK,IACnE,EACE,OAAO;IACL,QAAQ,MAAM;IACd,WAAW,MAAM;IACjB,OAAO,OAAO,MAAM,OAAO,KAAK;IAChC,KACE,OAAO,MAAM,OAAO,GAAG,KACvB,OAAO,MAAM,OAAO,OAAO,KAC3B,WAAW,MAAM,KAAK,GAAG,MAAM,YAAY,YAAY,MAAM;IAC/D,GAAI,OAAO,MAAM,OAAO,UAAU,IAAI,EAAE,WAAW,OAAO,MAAM,OAAO,UAAU,EAAE,IAAI,CAAC;IACxF,GAAI,OAAO,MAAM,OAAO,UAAU,IAAI,EAAE,WAAW,OAAO,MAAM,OAAO,UAAU,EAAE,IAAI,CAAC;IACxF,WAAW,UAAU,MAAM,OAAO,QAAQ,aAAa,MAAM,OAAO,SAAS;IAC7E,QAAQ,WAAW,MAAM,OAAO,UAAU,MAAM,OAAO,QAAQ,MAAM;IACrE,aAAa,YAAY,MAAM,OAAO,UAAU,MAAM,OAAO,QAAQ,MAAM;IAC3E,OAAO,OAAO,MAAM,OAAO,KAAK,MAAM,WAAY,WAAsB;IACxE,GAAI,cAAc,EAAE,QAAQ,YAAY,IAAI,CAAC;IAC7C,eAAe,MAAM;GACvB,EACF,IACA,CAAC;GACL,GAAI,MAAM,OAAO,UAAU,eAAe,OAAO,MAAM,EAAE,IACrD,EACE,MAAM;IACJ,IAAI,OAAO,MAAM,EAAE;IACnB,GAAI,OAAO,MAAM,IAAI,IAAI,EAAE,MAAM,OAAO,MAAM,IAAI,EAAE,IAAI,CAAC;IACzD,GAAI,OAAO,MAAM,GAAG,IAAI,EAAE,KAAK,OAAO,MAAM,GAAG,EAAE,IAAI,CAAC;IACtD,GAAI,OAAO,OAAO,MAAM,OAAO,QAAQ,IAAI,CAAC,EAAE,QAAQ,IAClD,EAAE,QAAQ,OAAO,OAAO,MAAM,OAAO,QAAQ,IAAI,CAAC,EAAE,QAAQ,EAAE,IAC9D,CAAC;IACL,GAAI,OAAO,MAAM,UAAU,IAAI,EAAE,WAAW,OAAO,MAAM,UAAU,EAAE,IAAI,CAAC;IAC1E,GAAI,OAAO,MAAM,UAAU,IAAI,EAAE,WAAW,OAAO,MAAM,UAAU,EAAE,IAAI,CAAC;GAC5E,EACF,IACA,CAAC;GACL,GAAI,MAAM,mBAAmB,MAAM,mBAAmB,OAAO,MAAM,cAAc,KAAK,IAClF,EACE,cAAc;IACZ,QAAQ,MAAM;IACd,WAAW,MAAM;IACjB,OAAO,OAAO,MAAM,cAAc,KAAK;IACvC,KACE,OAAO,MAAM,cAAc,GAAG,KAC9B,OAAO,MAAM,cAAc,OAAO,KAClC,WAAW,MAAM,KAAK,GAAG,MAAM,YAAY,oBAAoB,MAAM;IACvE,GAAI,OAAO,MAAM,cAAc,UAAU,IAAI,EAAE,WAAW,OAAO,MAAM,cAAc,UAAU,EAAE,IAAI,CAAC;IACtG,OACE,sBAAsB,YAAY,sBAAsB,WACnD,WACA;IACP,OAAO,QAAQ,MAAM,cAAc,KAAK,KAAK,QAAQ,MAAM,cAAc,gBAAgB,KAAK;IAC9F,QAAQ,MAAM,UAAU,wBAAwB,sBAAsB;IACtE,WAAW,UAAU,MAAM,OAAO,QAAQ,aAAa,MAAM,cAAc,SAAS;IACpF,WAAW,UAAU,MAAM,OAAO,QAAQ,aAAa,MAAM,cAAc,SAAS;IACpF,QAAQ,WAAW,MAAM,cAAc,UAAU,MAAM,OAAO,QAAQ,MAAM;IAC5E,aAAa,YAAY,MAAM,cAAc,UAAU,MAAM,OAAO,QAAQ,MAAM;IAClF,GAAI,qBAAqB,EAAE,QAAQ,mBAAmB,IAAI,CAAC;IAC3D,eAAe,MAAM;IACrB,iBAAiB,MAAM;IACvB,YAAY,OAAO,MAAM,cAAc,aAAa,KAAK;IACzD,YAAY,OAAO,MAAM,cAAc,aAAa,KAAK;GAC3D,EACF,IACA,CAAC;EACP;EACA,MAAM,aAAa,mBACjB,KAAK,QAAQ,QACb,MAAM,4BAA4B,WAAW,KAAA,IAAY,aAAa,OAAO,GAC7E,QACF;EACA,MAAM,OACJ,MAAM,4BAA4B,UAC9B,wBAAwB,KAAK,QAAQ,OAAO,OAAO,MAAM,KAAK,IAC5D,KAAA,IACA,YAAY,qBACd,gBAAgB,KAAK,QAAQ,OAAO,OAAO,YAAY,MAAM,KAAK;EAGxE,IAAI,MAAM,4BAA4B,WAAW,CAAC,MAAM,OAAO,EAAE,QAAQ,UAAU;EACnF,IAAI;EACJ,IAAI,YAAuC,CAAC;EAC5C,IAAI,UAA+E,EAAE,QAAQ,WAAW;EACxG,IAAI;GACF,WAAW,OAAO,MAAM,gBAAgB,QAAQ,QAAQ,KAAK,OAAO,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,KAAA;GACzF,IAAI,UAAU,SAAS,UACrB,UAAU;IAAE,QAAQ;IAAY,MAAM,SAAS;IAAM,QAAQ,SAAS;GAAO;QACxE,IAAI,UACT,YAAY,6BAA6B,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAI,UAAS;IAChE,4BACE,OACA,KAAK,QAAQ,QACb,MAAM,OAAO,iBAAiB,MAAM,IAAI,IAAI,KAAA,CAC9C;IACA,OAAO,EAAE,GAAG,MAAM;GACpB,CAAC;EAEL,SAAS,OAAO;GACd,MAAM,WAAW,iBAAiB,SAAS,MAAM,YAAY;GAC7D,UAAU;IACR,QAAQ;IACR,MAAM,WAAW,YAAY;IAC7B,QAAQ,WACJ,uCACA,iBAAiB,QACf,MAAM,QAAQ,MAAM,GAAG,GAAK,IAC5B;GACR;EACF;EAEA,MAAM,YAAY,MAAM,KAAK,QAAQ,QAAQ,qBAAqB;GAChE,OAAO,MAAM;GACb,kBAAkB,MAAM;GACxB,YAAY,MAAM,MAAM,MAAM;GAC9B,SAAS;IAAE,UAAU,MAAM;IAAiB,aAAa,UAAU,MAAM;GAAQ;GACjF,eAAe,KAAK,QAAQ;GAC5B,kBAAkB,MAAM,MAAM,YAAY;GAC1C,OAAO,EAAE,GAAG,MAAM,MAAM;GACxB;GACA;GACA,aAAa,CAAC;GACd,qBAAK,IAAI,KAAK;EAChB,CAAC;EACD,IAAI,UAAU,WAAW,SAAS;GAEhC,IAAI,WAAW,yBACb,MAAM,IAAI,MAAM,sCAAsC,MAAM,gBAAgB,6BAA6B;GAE3G,MAAM,QAAQ,MAAM,OAAO,MAAM,KAAK,QAAQ,QAAQ,IAAI;IAAE,OAAO,MAAM;IAAO,IAAI,MAAM,KAAK;GAAG,CAAC,IAAI;GACvG,IAAI,MAAM,QAAQ,CAAC,OAAO,OAAO,EAAE,QAAQ,UAAU;GACrD,OAAO,KAAK,UAAU;IAAE,GAAG;IAAO,MAAM,SAAS,KAAA;GAAU,GAAG,UAAU,CAAC;EAC3E;EACA,OAAO,EAAE,QAAQ,UAAU,OAAO;CACpC;AACF;AAEA,SAAgB,kBACd,QACA,SACgE;CAChE,IAAI,CAAC,QAAQ,SAAS,OAAO,KAAA;CAC7B,MAAM,QAAQ,IAAI,YAAY;EAC5B;EACA,eAAe,QAAQ,QAAQ;EAC/B,UAAU,QAAQ,QAAQ;EAC1B,SAAS,QAAQ,QAAQ;EACzB,QAAQ,QAAQ,QAAQ;EACxB,eAAe,QAAQ,QAAQ;EAC/B,QAAQ,QAAQ,QAAQ;CAC1B,CAAC;CACD,QAAO,UAAS,MAAM,OAAO,KAAK;AACpC"}
|
|
@@ -3,7 +3,7 @@ import { subscribeToMergeRequest, unsubscribeFromMergeRequest } from "./subscrip
|
|
|
3
3
|
import { normalizeGitLabHost } from "./integration.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { createTool } from "@mastra/core/tools";
|
|
6
|
-
|
|
6
|
+
// src/integrations/gitlab/session-subscriptions.ts
|
|
7
7
|
const MERGE_REQUEST_URL = /^https?:\/\/([^/\s]+)\/(.+?)\/-\/merge_requests\/(\d+)\/?$/i;
|
|
8
8
|
function sessionUserId(requestContext) {
|
|
9
9
|
return getFactoryAuthUserId(getFactoryAuthUserFromContext(requestContext));
|
|
@@ -186,7 +186,6 @@ function parseCreatedMergeRequest(context) {
|
|
|
186
186
|
if (typeof url !== "string" || !parseMergeRequestUrl(url)) return void 0;
|
|
187
187
|
return url.trim().replace(/\/$/, "");
|
|
188
188
|
}
|
|
189
|
-
//#endregion
|
|
190
189
|
export { createGitLabSubscriptionTools, parseCreatedMergeRequest, parseMergeRequestUrl, subscribeCurrentSessionToMergeRequest, unsubscribeCurrentSessionFromMergeRequest };
|
|
191
190
|
|
|
192
191
|
//# sourceMappingURL=session-subscriptions.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/integrations/gitlab/subscriptions.ts
|
|
2
2
|
function normalizeSubscriptionHost(host) {
|
|
3
3
|
return host.trim().toLowerCase().replace(/\.$/, "");
|
|
4
4
|
}
|
|
@@ -70,7 +70,6 @@ async function retireMergeRequestSubscriptions(input, storage) {
|
|
|
70
70
|
const rows = await storage.subscriptions.listByTarget(mergeRequestTargetKey(input));
|
|
71
71
|
await Promise.all(rows.filter((row) => row.status === "open").map((row) => storage.subscriptions.updateStatus(row.id, input.merged ? "merged" : "closed")));
|
|
72
72
|
}
|
|
73
|
-
//#endregion
|
|
74
73
|
export { listMergeRequestSubscriptions, listMergeRequestSubscriptionsForThread, listMergeRequestSubscriptionsForWebhook, mergeRequestTargetKey, mergeRequestUrl, normalizeSubscriptionHost, retireMergeRequestSubscription, retireMergeRequestSubscriptions, subscribeToMergeRequest, unsubscribeFromMergeRequest };
|
|
75
74
|
|
|
76
75
|
//# sourceMappingURL=subscriptions.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GitLabApiError } from "./api.js";
|
|
2
|
-
|
|
2
|
+
// src/integrations/gitlab/version-control.ts
|
|
3
3
|
function buildGitLabVersionControl(deps) {
|
|
4
4
|
let storage;
|
|
5
5
|
const sourceControlStorage = () => {
|
|
@@ -649,7 +649,6 @@ function normalizeSlug(value) {
|
|
|
649
649
|
if (!slug || segments.some((segment) => !/^[A-Za-z0-9_.-]+$/.test(segment) || segment === "." || segment === "..")) throw new GitLabApiError("GitLab repository slug is invalid.", 400);
|
|
650
650
|
return slug;
|
|
651
651
|
}
|
|
652
|
-
//#endregion
|
|
653
652
|
export { buildGitLabVersionControl };
|
|
654
653
|
|
|
655
654
|
//# sourceMappingURL=version-control.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolveSubscriptionSession, subscriptionRunContext } from "../subscription-session.js";
|
|
2
2
|
import { listMergeRequestSubscriptionsForWebhook, mergeRequestUrl, normalizeSubscriptionHost, retireMergeRequestSubscription } from "./subscriptions.js";
|
|
3
3
|
import "./integration.js";
|
|
4
|
-
|
|
4
|
+
// src/integrations/gitlab/webhook-dispatch.ts
|
|
5
5
|
function getObject(value) {
|
|
6
6
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
7
7
|
}
|
|
@@ -229,7 +229,6 @@ async function dispatchGitLabWebhook(parsed, dependencies) {
|
|
|
229
229
|
ignored: false
|
|
230
230
|
};
|
|
231
231
|
}
|
|
232
|
-
//#endregion
|
|
233
232
|
export { classifyGitLabWebhook, dispatchGitLabWebhook, gitlabWebhookHost };
|
|
234
233
|
|
|
235
234
|
//# sourceMappingURL=webhook-dispatch.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { dispatchGitLabWebhook } from "./webhook-dispatch.js";
|
|
2
2
|
import { timingSafeEqual } from "crypto";
|
|
3
|
-
|
|
3
|
+
// src/integrations/gitlab/webhook.ts
|
|
4
4
|
const SUPPORTED_GITLAB_WEBHOOK_EVENTS = /* @__PURE__ */ new Set([
|
|
5
5
|
"Issue Hook",
|
|
6
6
|
"Note Hook",
|
|
@@ -195,7 +195,6 @@ async function handleGitLabWebhook(c, options) {
|
|
|
195
195
|
const { webhookSecret: _secret, ...process } = options;
|
|
196
196
|
return processGitLabWebhook(parsed, process);
|
|
197
197
|
}
|
|
198
|
-
//#endregion
|
|
199
198
|
export { SUPPORTED_GITLAB_WEBHOOK_EVENTS, handleGitLabWebhook, normalizeGitLabWebhookMetadata, parseGitLabWebhook, parseGitLabWebhookBody, processGitLabWebhook, verifyGitLabToken };
|
|
200
199
|
|
|
201
200
|
//# sourceMappingURL=webhook.js.map
|
|
@@ -2,7 +2,7 @@ import { IncidentioApiError } from "./api.js";
|
|
|
2
2
|
import { scopeSourceIdsToProject } from "./routes.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { createTool } from "@mastra/core/tools";
|
|
5
|
-
|
|
5
|
+
// src/integrations/incidentio/agent-tools.ts
|
|
6
6
|
/**
|
|
7
7
|
* Prompt-injection boundary: follow-up titles and descriptions are authored by
|
|
8
8
|
* third parties, so the tool labels them as evidence rather than letting them
|
|
@@ -84,7 +84,6 @@ async function buildIncidentioAgentTools({ requestContext, incidentio }) {
|
|
|
84
84
|
if (!orgId) return {};
|
|
85
85
|
return { incidentio_get_issue: createIncidentioGetIssueTool(incidentio, orgId, projectId) };
|
|
86
86
|
}
|
|
87
|
-
//#endregion
|
|
88
87
|
export { INCIDENTIO_UNTRUSTED_CONTENT_NOTICE, buildIncidentioAgentTools };
|
|
89
88
|
|
|
90
89
|
//# sourceMappingURL=agent-tools.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/integrations/incidentio/api.ts
|
|
2
2
|
var IncidentioApiError = class extends Error {
|
|
3
3
|
status;
|
|
4
4
|
constructor(message, status) {
|
|
@@ -189,7 +189,6 @@ var IncidentioApiClient = class {
|
|
|
189
189
|
return await response.json();
|
|
190
190
|
}
|
|
191
191
|
};
|
|
192
|
-
//#endregion
|
|
193
192
|
export { IncidentioApiClient, IncidentioApiError };
|
|
194
193
|
|
|
195
194
|
//# sourceMappingURL=api.js.map
|