@mastra/factory 0.13.0-alpha.3 → 0.13.0-alpha.5

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.
Files changed (69) hide show
  1. package/dist/factory.js +1 -1
  2. package/dist/integrations/github/acceptance-labels.d.ts +0 -1
  3. package/dist/integrations/github/acceptance-labels.d.ts.map +1 -1
  4. package/dist/integrations/github/acceptance-labels.js +2 -2
  5. package/dist/integrations/github/acceptance-labels.js.map +1 -1
  6. package/dist/integrations/github/routes.d.ts.map +1 -1
  7. package/dist/integrations/github/routes.js +2 -1
  8. package/dist/integrations/github/routes.js.map +1 -1
  9. package/dist/integrations/github/rules.d.ts.map +1 -1
  10. package/dist/integrations/github/rules.js +2 -1
  11. package/dist/integrations/github/rules.js.map +1 -1
  12. package/dist/integrations/linear/rules.d.ts.map +1 -1
  13. package/dist/integrations/linear/rules.js +1 -0
  14. package/dist/integrations/linear/rules.js.map +1 -1
  15. package/dist/routes/attention-proposed.d.ts +3 -0
  16. package/dist/routes/attention-proposed.d.ts.map +1 -0
  17. package/dist/routes/attention-proposed.js +21 -0
  18. package/dist/routes/attention-proposed.js.map +1 -0
  19. package/dist/routes/attention-providers.d.ts +16 -4
  20. package/dist/routes/attention-providers.d.ts.map +1 -1
  21. package/dist/routes/attention-providers.js +53 -46
  22. package/dist/routes/attention-providers.js.map +1 -1
  23. package/dist/routes/attention.d.ts.map +1 -1
  24. package/dist/routes/attention.js +22 -28
  25. package/dist/routes/attention.js.map +1 -1
  26. package/dist/routes/config.d.ts +2 -0
  27. package/dist/routes/config.d.ts.map +1 -1
  28. package/dist/routes/config.js +3 -2
  29. package/dist/routes/config.js.map +1 -1
  30. package/dist/routes/surface.d.ts.map +1 -1
  31. package/dist/routes/surface.js +10 -6
  32. package/dist/routes/surface.js.map +1 -1
  33. package/dist/routes/work-items.d.ts.map +1 -1
  34. package/dist/routes/work-items.js +9 -40
  35. package/dist/routes/work-items.js.map +1 -1
  36. package/dist/rules/defaults.d.ts.map +1 -1
  37. package/dist/rules/defaults.js +44 -8
  38. package/dist/rules/defaults.js.map +1 -1
  39. package/dist/rules/dispatcher.d.ts.map +1 -1
  40. package/dist/rules/dispatcher.js +5 -2
  41. package/dist/rules/dispatcher.js.map +1 -1
  42. package/dist/rules/index.js +1 -1
  43. package/dist/rules/processor.d.ts.map +1 -1
  44. package/dist/rules/processor.js +2 -1
  45. package/dist/rules/processor.js.map +1 -1
  46. package/dist/rules/start-coordinator.d.ts +3 -16
  47. package/dist/rules/start-coordinator.d.ts.map +1 -1
  48. package/dist/rules/start-coordinator.js +12 -43
  49. package/dist/rules/start-coordinator.js.map +1 -1
  50. package/dist/rules/transition-service.d.ts.map +1 -1
  51. package/dist/rules/transition-service.js +9 -8
  52. package/dist/rules/transition-service.js.map +1 -1
  53. package/dist/rules/types.d.ts +9 -0
  54. package/dist/rules/types.d.ts.map +1 -1
  55. package/dist/rules/types.js +9 -1
  56. package/dist/rules/types.js.map +1 -1
  57. package/dist/storage/domains/work-items/base.d.ts +8 -18
  58. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  59. package/dist/storage/domains/work-items/base.js +52 -37
  60. package/dist/storage/domains/work-items/base.js.map +1 -1
  61. package/dist/supervisor/health.d.ts.map +1 -1
  62. package/dist/supervisor/health.js +1 -2
  63. package/dist/supervisor/health.js.map +1 -1
  64. package/dist/work-item-branch.d.ts +6 -0
  65. package/dist/work-item-branch.d.ts.map +1 -1
  66. package/dist/work-item-branch.js +15 -9
  67. package/dist/work-item-branch.js.map +1 -1
  68. package/dist/workspace.js +1 -1
  69. package/package.json +7 -7
package/dist/factory.js CHANGED
@@ -12,7 +12,6 @@ import { createCustomProvidersPrimer, registerCustomProvidersSource } from "./ro
12
12
  import { ProjectRoutes } from "./routes/projects.js";
13
13
  import { MemorySettingsStorage } from "./storage/domains/memory-settings/base.js";
14
14
  import { hydrateSessionMemorySettings } from "./session/memory-settings-hydration.js";
15
- import { FactoryFeedReader } from "./storage/domains/comments/feed-context.js";
16
15
  import { FactoryTransitionService } from "./rules/transition-service.js";
17
16
  import { SourceControlStorage } from "./storage/domains/source-control/base.js";
18
17
  import { hydrateSessionModelPack } from "./session/model-pack-hydration.js";
@@ -26,6 +25,7 @@ import { createTenantCredentialPrimer, primeTenantCredentials, registerTenantCre
26
25
  import { QueueHealthStorage } from "./storage/domains/queue-health/base.js";
27
26
  import { assembleFactoryApiRoutes, buildIntegrationContext } from "./routes/surface.js";
28
27
  import { builtInFactoryRules } from "./rules/defaults.js";
28
+ import { FactoryFeedReader } from "./storage/domains/comments/feed-context.js";
29
29
  import { FactoryDecisionDispatcher } from "./rules/dispatcher.js";
30
30
  import { FactoryPhaseStateProcessor } from "./rules/processor.js";
31
31
  import { createTerminalStageCleanup } from "./rules/terminal-cleanup.js";
@@ -1,7 +1,6 @@
1
1
  import type { SourceControlStorageHandle } from '../../storage/domains/source-control/base.js';
2
2
  import type { WorkItemRow } from '../../storage/domains/work-items/base.js';
3
3
  import type { GithubIntegration } from './integration.js';
4
- export declare const NEEDS_APPROVAL_LABEL = "status: needs approval";
5
4
  export interface ReconcileAcceptanceLabelsInput {
6
5
  orgId: string;
7
6
  factoryProjectId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"acceptance-labels.d.ts","sourceRoot":"","sources":["../../../src/integrations/github/acceptance-labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8CAA8C,CAAC;AAC/F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAE7D,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,0BAA0B,EACzC,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,IAAI,CAAC,CAgBf"}
1
+ {"version":3,"file":"acceptance-labels.d.ts","sourceRoot":"","sources":["../../../src/integrations/github/acceptance-labels.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8CAA8C,CAAC;AAC/F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,0BAA0B,EACzC,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,IAAI,CAAC,CAgBf"}
@@ -1,5 +1,5 @@
1
+ import { NEEDS_APPROVAL_LABEL } from "../../rules/types.js";
1
2
  //#region src/integrations/github/acceptance-labels.ts
2
- const NEEDS_APPROVAL_LABEL = "status: needs approval";
3
3
  /**
4
4
  * Reflect a maintainer's acceptance of a triaged GitHub issue back on the
5
5
  * issue: the triage skill stamps `status: needs approval` and never removes it,
@@ -50,6 +50,6 @@ async function resolveRepository(sourceControl, orgId, factoryProjectId, externa
50
50
  }
51
51
  }
52
52
  //#endregion
53
- export { NEEDS_APPROVAL_LABEL, reconcileGithubAcceptanceLabels };
53
+ export { reconcileGithubAcceptanceLabels };
54
54
 
55
55
  //# sourceMappingURL=acceptance-labels.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"acceptance-labels.js","names":[],"sources":["../../../src/integrations/github/acceptance-labels.ts"],"sourcesContent":["import type { SourceControlStorageHandle } from '../../storage/domains/source-control/base.js';\nimport type { WorkItemRow } from '../../storage/domains/work-items/base.js';\nimport type { GithubIntegration } from './integration.js';\n\nexport const NEEDS_APPROVAL_LABEL = 'status: needs approval';\n\nexport interface ReconcileAcceptanceLabelsInput {\n orgId: string;\n factoryProjectId: string;\n item: WorkItemRow;\n}\n\n/**\n * Reflect a maintainer's acceptance of a triaged GitHub issue back on the\n * issue: the triage skill stamps `status: needs approval` and never removes it,\n * so the approval gesture on the board is the only point that can clear it.\n * Best-effort — every failure is a warning, never a rejected transition.\n */\nexport async function reconcileGithubAcceptanceLabels(\n github: GithubIntegration,\n sourceControl: SourceControlStorageHandle,\n input: ReconcileAcceptanceLabelsInput,\n): Promise<void> {\n const { item } = input;\n if (item.externalSource?.integrationId !== 'github' || item.externalSource.type !== 'issue') return;\n const repositoryId = item.metadata?.githubRepositoryId;\n const issueNumber = item.metadata?.githubIssueNumber;\n if (typeof repositoryId !== 'number' || typeof issueNumber !== 'number' || issueNumber < 1) return;\n\n try {\n const target = await resolveRepository(sourceControl, input.orgId, input.factoryProjectId, repositoryId);\n if (!target) return;\n await github.removeIssueLabel(target.installationId, target.slug, issueNumber, NEEDS_APPROVAL_LABEL);\n } catch (error) {\n // GitHub answers 404 when the label is not on the issue; nothing to clear.\n if ((error as { status?: number }).status === 404) return;\n console.warn(`[factory] could not clear \"${NEEDS_APPROVAL_LABEL}\" for work item ${item.id}:`, error);\n }\n}\n\nasync function resolveRepository(\n sourceControl: SourceControlStorageHandle,\n orgId: string,\n factoryProjectId: string,\n externalRepositoryId: number,\n): Promise<{ installationId: number; slug: string } | undefined> {\n for (const connection of await sourceControl.connections.list({ orgId, factoryProjectId })) {\n const installation = await sourceControl.installations.get({ orgId, id: connection.installationId });\n if (!installation) continue;\n for (const link of await sourceControl.projectRepositories.list({ orgId, connectionId: connection.id })) {\n const repository = await sourceControl.repositories.get({ orgId, id: link.repositoryId });\n if (!repository || Number(repository.externalId) !== externalRepositoryId) continue;\n const installationId = Number(installation.externalId);\n if (!Number.isInteger(installationId)) return undefined;\n return { installationId, slug: repository.slug };\n }\n }\n return undefined;\n}\n"],"mappings":";AAIA,MAAa,uBAAuB;;;;;;;AAcpC,eAAsB,gCACpB,QACA,eACA,OACe;CACf,MAAM,EAAE,SAAS;CACjB,IAAI,KAAK,gBAAgB,kBAAkB,YAAY,KAAK,eAAe,SAAS,SAAS;CAC7F,MAAM,eAAe,KAAK,UAAU;CACpC,MAAM,cAAc,KAAK,UAAU;CACnC,IAAI,OAAO,iBAAiB,YAAY,OAAO,gBAAgB,YAAY,cAAc,GAAG;CAE5F,IAAI;EACF,MAAM,SAAS,MAAM,kBAAkB,eAAe,MAAM,OAAO,MAAM,kBAAkB,YAAY;EACvG,IAAI,CAAC,QAAQ;EACb,MAAM,OAAO,iBAAiB,OAAO,gBAAgB,OAAO,MAAM,aAAa,oBAAoB;CACrG,SAAS,OAAO;EAEd,IAAK,MAA8B,WAAW,KAAK;EACnD,QAAQ,KAAK,8BAA8B,qBAAqB,kBAAkB,KAAK,GAAG,IAAI,KAAK;CACrG;AACF;AAEA,eAAe,kBACb,eACA,OACA,kBACA,sBAC+D;CAC/D,KAAK,MAAM,cAAc,MAAM,cAAc,YAAY,KAAK;EAAE;EAAO;CAAiB,CAAC,GAAG;EAC1F,MAAM,eAAe,MAAM,cAAc,cAAc,IAAI;GAAE;GAAO,IAAI,WAAW;EAAe,CAAC;EACnG,IAAI,CAAC,cAAc;EACnB,KAAK,MAAM,QAAQ,MAAM,cAAc,oBAAoB,KAAK;GAAE;GAAO,cAAc,WAAW;EAAG,CAAC,GAAG;GACvG,MAAM,aAAa,MAAM,cAAc,aAAa,IAAI;IAAE;IAAO,IAAI,KAAK;GAAa,CAAC;GACxF,IAAI,CAAC,cAAc,OAAO,WAAW,UAAU,MAAM,sBAAsB;GAC3E,MAAM,iBAAiB,OAAO,aAAa,UAAU;GACrD,IAAI,CAAC,OAAO,UAAU,cAAc,GAAG,OAAO,KAAA;GAC9C,OAAO;IAAE;IAAgB,MAAM,WAAW;GAAK;EACjD;CACF;AAEF"}
1
+ {"version":3,"file":"acceptance-labels.js","names":[],"sources":["../../../src/integrations/github/acceptance-labels.ts"],"sourcesContent":["import { NEEDS_APPROVAL_LABEL } from '../../rules/types.js';\nimport type { SourceControlStorageHandle } from '../../storage/domains/source-control/base.js';\nimport type { WorkItemRow } from '../../storage/domains/work-items/base.js';\nimport type { GithubIntegration } from './integration.js';\n\nexport interface ReconcileAcceptanceLabelsInput {\n orgId: string;\n factoryProjectId: string;\n item: WorkItemRow;\n}\n\n/**\n * Reflect a maintainer's acceptance of a triaged GitHub issue back on the\n * issue: the triage skill stamps `status: needs approval` and never removes it,\n * so the approval gesture on the board is the only point that can clear it.\n * Best-effort — every failure is a warning, never a rejected transition.\n */\nexport async function reconcileGithubAcceptanceLabels(\n github: GithubIntegration,\n sourceControl: SourceControlStorageHandle,\n input: ReconcileAcceptanceLabelsInput,\n): Promise<void> {\n const { item } = input;\n if (item.externalSource?.integrationId !== 'github' || item.externalSource.type !== 'issue') return;\n const repositoryId = item.metadata?.githubRepositoryId;\n const issueNumber = item.metadata?.githubIssueNumber;\n if (typeof repositoryId !== 'number' || typeof issueNumber !== 'number' || issueNumber < 1) return;\n\n try {\n const target = await resolveRepository(sourceControl, input.orgId, input.factoryProjectId, repositoryId);\n if (!target) return;\n await github.removeIssueLabel(target.installationId, target.slug, issueNumber, NEEDS_APPROVAL_LABEL);\n } catch (error) {\n // GitHub answers 404 when the label is not on the issue; nothing to clear.\n if ((error as { status?: number }).status === 404) return;\n console.warn(`[factory] could not clear \"${NEEDS_APPROVAL_LABEL}\" for work item ${item.id}:`, error);\n }\n}\n\nasync function resolveRepository(\n sourceControl: SourceControlStorageHandle,\n orgId: string,\n factoryProjectId: string,\n externalRepositoryId: number,\n): Promise<{ installationId: number; slug: string } | undefined> {\n for (const connection of await sourceControl.connections.list({ orgId, factoryProjectId })) {\n const installation = await sourceControl.installations.get({ orgId, id: connection.installationId });\n if (!installation) continue;\n for (const link of await sourceControl.projectRepositories.list({ orgId, connectionId: connection.id })) {\n const repository = await sourceControl.repositories.get({ orgId, id: link.repositoryId });\n if (!repository || Number(repository.externalId) !== externalRepositoryId) continue;\n const installationId = Number(installation.externalId);\n if (!Number.isInteger(installationId)) return undefined;\n return { installationId, slug: repository.slug };\n }\n }\n return undefined;\n}\n"],"mappings":";;;;;;;;AAiBA,eAAsB,gCACpB,QACA,eACA,OACe;CACf,MAAM,EAAE,SAAS;CACjB,IAAI,KAAK,gBAAgB,kBAAkB,YAAY,KAAK,eAAe,SAAS,SAAS;CAC7F,MAAM,eAAe,KAAK,UAAU;CACpC,MAAM,cAAc,KAAK,UAAU;CACnC,IAAI,OAAO,iBAAiB,YAAY,OAAO,gBAAgB,YAAY,cAAc,GAAG;CAE5F,IAAI;EACF,MAAM,SAAS,MAAM,kBAAkB,eAAe,MAAM,OAAO,MAAM,kBAAkB,YAAY;EACvG,IAAI,CAAC,QAAQ;EACb,MAAM,OAAO,iBAAiB,OAAO,gBAAgB,OAAO,MAAM,aAAa,oBAAoB;CACrG,SAAS,OAAO;EAEd,IAAK,MAA8B,WAAW,KAAK;EACnD,QAAQ,KAAK,8BAA8B,qBAAqB,kBAAkB,KAAK,GAAG,IAAI,KAAK;CACrG;AACF;AAEA,eAAe,kBACb,eACA,OACA,kBACA,sBAC+D;CAC/D,KAAK,MAAM,cAAc,MAAM,cAAc,YAAY,KAAK;EAAE;EAAO;CAAiB,CAAC,GAAG;EAC1F,MAAM,eAAe,MAAM,cAAc,cAAc,IAAI;GAAE;GAAO,IAAI,WAAW;EAAe,CAAC;EACnG,IAAI,CAAC,cAAc;EACnB,KAAK,MAAM,QAAQ,MAAM,cAAc,oBAAoB,KAAK;GAAE;GAAO,cAAc,WAAW;EAAG,CAAC,GAAG;GACvG,MAAM,aAAa,MAAM,cAAc,aAAa,IAAI;IAAE;IAAO,IAAI,KAAK;GAAa,CAAC;GACxF,IAAI,CAAC,cAAc,OAAO,WAAW,UAAU,MAAM,sBAAsB;GAC3E,MAAM,iBAAiB,OAAO,aAAa,UAAU;GACrD,IAAI,CAAC,OAAO,UAAU,cAAc,GAAG,OAAO,KAAA;GAC9C,OAAO;IAAE;IAAgB,MAAM,WAAW;GAAK;EACjD;CACF;AAEF"}
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/integrations/github/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAInF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AAC3F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AASrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAuC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAgBxD,MAAM,WAAW,wBAAwB;IACvC,4EAA4E;IAC5E,IAAI,EAAE,SAAS,CAAC;IAChB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,wBAAwB,CAAC;IACjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,yEAAyE;IACzE,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,UAAU,CAAC,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAC7C,gGAAgG;IAChG,cAAc,EAAE,IAAI,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;IACnD,6EAA6E;IAC7E,SAAS,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,iBAAiB,CAAC,EAAE,OAAO,qCAAqC,EAAE,4BAA4B,CAAC;IAC/F,kFAAkF;IAClF,SAAS,CAAC,EAAE,IAAI,CAAC,OAAO,0CAA0C,EAAE,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;IAChH,+FAA+F;IAC/F,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACvE;AA4ND;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,QAAQ,EAAE,CAmoB/E;AA+GD,KAAK,wBAAwB,GAAG,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/integrations/github/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIvD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAInF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AAC3F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AASrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAuC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAgBxD,MAAM,WAAW,wBAAwB;IACvC,4EAA4E;IAC5E,IAAI,EAAE,SAAS,CAAC;IAChB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,wBAAwB,CAAC;IACjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,yEAAyE;IACzE,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,UAAU,CAAC,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAC7C,gGAAgG;IAChG,cAAc,EAAE,IAAI,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;IACnD,6EAA6E;IAC7E,SAAS,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,iBAAiB,CAAC,EAAE,OAAO,qCAAqC,EAAE,4BAA4B,CAAC;IAC/F,kFAAkF;IAClF,SAAS,CAAC,EAAE,IAAI,CAAC,OAAO,0CAA0C,EAAE,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;IAChH,+FAA+F;IAC/F,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACvE;AA4ND;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,QAAQ,EAAE,CAmoB/E;AA+GD,KAAK,wBAAwB,GAAG,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { AUTO_TRIAGED_LABEL, NEEDS_APPROVAL_LABEL } from "../../rules/types.js";
1
2
  import { clearGithubPat, getGithubPatStatus, setGithubPat } from "./pat.js";
2
3
  import { listPullRequestSubscriptionsForThread, subscribeToPullRequest } from "./subscriptions.js";
3
4
  import { MaterializeError, SetupCommandError, commitAll, isValidGitRef, pushBranch } from "./sandbox.js";
@@ -104,7 +105,7 @@ function parseResourceNumber(raw) {
104
105
  const parsed = Number(raw);
105
106
  return parsed > 0 ? parsed : null;
106
107
  }
107
- const VALID_ISSUE_LABEL_FILTERS = /* @__PURE__ */ new Set(["status: auto-triaged", "status: needs approval"]);
108
+ const VALID_ISSUE_LABEL_FILTERS = /* @__PURE__ */ new Set([AUTO_TRIAGED_LABEL, NEEDS_APPROVAL_LABEL]);
108
109
  function parseIssueLabelFilter(raw) {
109
110
  if (raw === void 0 || raw === "") return void 0;
110
111
  if (VALID_ISSUE_LABEL_FILTERS.has(raw)) return raw;
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","names":["isValidGitRefSandbox"],"sources":["../../../src/integrations/github/routes.ts"],"sourcesContent":["/**\n * Mastra `apiRoutes` for the GitHub App project feature.\n *\n * Registered alongside the other `/web/*` routes, behind the host auth gate.\n * Every route additionally re-checks the authenticated user via the injected\n * `RouteAuth` seam and scopes all rows by that user's stable id, so a user can\n * only ever see and operate on their own installations and projects.\n *\n * When the feature is disabled (`isGithubFeatureEnabled()` false), `buildGithubRoutes`\n * returns only `GET /web/github/status`, which reports `enabled:false`\n * so the SPA can cleanly hide all GitHub UI.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { MountedMastraCode } from '@mastra/code-sdk';\nimport { resolveModel } from '@mastra/code-sdk/agents/model';\nimport { RequestContext } from '@mastra/core/request-context';\nimport type { ApiRoute, IUserProvider } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport { UniqueViolationError } from '@mastra/core/storage';\nimport type { FactoryStorage } from '@mastra/core/storage';\nimport type { Context } from 'hono';\nimport type { RouteAuth } from '../../routes/route.js';\nimport { requireExec } from '../../sandbox/materialization.js';\nimport type { ExecutableSandbox } from '../../sandbox/materialization.js';\nimport type { MastraFactorySandboxConfig } from '../../sandbox/session-sandbox.js';\nimport { peekSessionSandbox } from '../../sandbox/session-sandbox.js';\nimport { sanitizeSegment } from '../../sandbox/workdir.js';\nimport { normalizeSessionTitle } from '../../session/session-title.js';\nimport type { StateSigner } from '../../state-signing.js';\nimport type { AuditEmitter } from '../../storage/domains/audit/domain.js';\nimport type { MemorySettingsStorage } from '../../storage/domains/memory-settings/base.js';\nimport type { FactoryProjectsStorage } from '../../storage/domains/projects/base.js';\nimport type {\n ProjectRepository,\n ProjectSourceControlConnection,\n SourceControlInstallation,\n SourceControlRepository,\n} from '../../storage/domains/source-control/base.js';\nimport { listRepositoryCommits } from './commits.js';\nimport { getGithubFeatureDiagnostics, isGithubFeatureEnabled } from './config.js';\nimport type { GithubIntegration } from './integration.js';\nimport { clearGithubPat, getGithubPat, getGithubPatStatus, setGithubPat } from './pat.js';\nimport type { GithubPatKind } from './pat.js';\n\nimport { reclaimDeletedSessionSandbox } from './sandbox-release.js';\nimport {\n commitAll,\n isValidGitRef as isValidGitRefSandbox,\n MaterializeError,\n pushBranch,\n SetupCommandError,\n} from './sandbox.js';\nimport type { GitIdentity } from './sandbox.js';\n\nconst sessionOperationLocks = new Map<string, Promise<unknown>>();\nconst USER_SESSION_BRANCH_PREFIX = 'user/session-';\n// lowercase only (crypto.randomUUID output), so casing cannot fork one logical ID into two sessions\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;\n/**\n * Serialize same-session mutations within one Factory process. Factory sessions\n * normally issue these operations sequentially, so this lock is probably not\n * necessary; keep the cheap local guard until that invariant is enforced by\n * the request protocol. It intentionally does not consume a database connection.\n */\nfunction withSessionOperationLock<T>(sessionId: string, fn: () => Promise<T>): Promise<T> {\n const previous = sessionOperationLocks.get(sessionId) ?? Promise.resolve();\n const next = previous.then(fn, fn);\n const tail = next.then(\n () => undefined,\n () => undefined,\n );\n sessionOperationLocks.set(sessionId, tail);\n void tail.then(() => {\n if (sessionOperationLocks.get(sessionId) === tail) sessionOperationLocks.delete(sessionId);\n });\n return next;\n}\nimport { listPullRequestSubscriptionsForThread, subscribeToPullRequest } from './subscriptions.js';\nimport { handleGithubWebhook } from './webhook.js';\nimport type { ParsedGithubWebhook } from './webhook.js';\n\n/**\n * Loose Hono context accepted by the shared GitHub route helpers. The\n * `registerApiRoute` handlers receive a path-parameterized context whose\n * `HonoRequest` literal-path generics are invariant and don't flow into a\n * shared helper signature. The helpers only ever touch cookies/query/tenant, so\n * we erase the path to a plain `Context` at the call boundary via `loose()`.\n */\ntype RouteContext = Context;\n\n/** Erase a route handler's path-parameterized context to a plain `Context`. */\nfunction loose(c: unknown): RouteContext {\n return c as RouteContext;\n}\n\nexport interface MountGithubRoutesOptions {\n /** Host auth seam — resolves the signed-in user/tenant for each request. */\n auth: RouteAuth;\n /** Optional user directory used to resolve session-owner display profiles. */\n users?: SessionOwnerUserProvider;\n /**\n * The host's session-sandbox callback. Routes only read whether it is\n * configured: without one, `/web/github/status` reports\n * `sandboxEnabled: false` and sandbox-backed routes respond 503. Sandboxes\n * themselves are constructed per session and started lazily elsewhere.\n */\n sandbox?: MastraFactorySandboxConfig;\n /** Factory storage backend used for the `appDbConfigured` diagnostic. */\n storage?: FactoryStorage;\n /**\n * The GitHub App integration the handlers operate on (Octokit access, token\n * minting, OAuth URLs). Normally supplied by `GithubIntegration.routes()`;\n * when absent, only the disabled `status` route is served.\n */\n github?: GithubIntegration;\n /**\n * Shared OAuth/install `state` signer (created once per boot by the\n * factory). Required for the OAuth/install flow; when absent, only the\n * disabled `status` route is served.\n */\n stateSigner?: StateSigner;\n /**\n * Absolute base URL of the web server (e.g. `http://localhost:4111`), used to\n * build the OAuth/install redirect URI when one isn't explicitly configured.\n */\n baseUrl?: string;\n /** Explicit OAuth callback URI; defaults to `<baseUrl>/auth/github/callback`. */\n redirectUri?: string;\n /** Controller used to route verified webhook notifications to exact subscribed sessions. */\n controller?: MountedMastraCode['controller'];\n /** Owner-scoped observational-memory settings — the source of the model that names a thread. */\n memorySettings: Pick<MemorySettingsStorage, 'get'>;\n /** Best-effort audit emission supplied by the factory-owned audit domain. */\n emitAudit?: AuditEmitter['emit'];\n /** Factory projects domain — resolves a project's default triage model. */\n projects?: FactoryProjectsStorage;\n sessionRetirement?: import('../../sandbox/session-retirement.js').SessionRetirementCoordinator;\n /** Work-items domain — session deletion strips the refs work items hold on it. */\n workItems?: Pick<import('../../storage/domains/work-items/base.js').WorkItemsStorage, 'clearSessionReferences'>;\n /** Authoritative Factory rule ingress for normalized, signature-verified GitHub deliveries. */\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n}\n\nfunction pullRequestNumberFromUrl(value: string, expectedRepo: string): number | undefined {\n try {\n const url = new URL(value);\n const match = url.pathname.match(/^\\/([^/]+\\/[^/]+)\\/pull\\/(\\d+)\\/?$/);\n if (\n url.protocol !== 'https:' ||\n url.hostname !== 'github.com' ||\n match?.[1]?.toLowerCase() !== expectedRepo.toLowerCase()\n ) {\n return undefined;\n }\n const number = Number(match[2]);\n return Number.isInteger(number) && number > 0 ? number : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Validate a git branch/ref name against a strict whitelist. The value is later\n * interpolated into a shell `git clone --branch` command, so it must never\n * contain shell metacharacters. We accept only git-ref-safe characters and\n * reject anything else rather than relying on shell quoting alone.\n */\nfunction isValidGitRef(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 && value.length <= 255 && /^[A-Za-z0-9_./-]+$/.test(value);\n}\n\nfunction isJsonObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Resolve the org-scoped tenant for a GitHub request. GitHub project features\n * are org-owned, so they require both a signed-in user and a WorkOS\n * organization. Returns the `(orgId, userId)` tenant (with `orgId` narrowed to a\n * non-null string) or a ready-to-return error response: 401 when unauthenticated,\n * 403 when the user has no organization (personal account).\n *\n * Resolves the session from the request cookie itself (via `auth.ensureUser`)\n * instead of relying on the auth gate's context stash: on platform deploys\n * custom `apiRoutes` run on an isolated sub-app context where the gate's\n * `c.set(...)` is invisible. When the gate stash IS visible (local Hono\n * server), `auth.ensureUser` returns the cached user and this is a no-op.\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' }, 401) };\n if (!tenant.orgId) {\n return {\n response: c.json(\n {\n error: 'organization_required',\n message: 'GitHub projects require a WorkOS organization. Personal accounts cannot connect repositories.',\n },\n 403,\n ),\n };\n }\n return { tenant: { orgId: tenant.orgId, userId: tenant.userId } };\n}\n\n/**\n * Parse a 1-based `page` query param. Missing means page 1; anything that is\n * not a small positive integer is rejected (`null`).\n */\nfunction parseListPage(raw: string | undefined): number | null {\n if (raw === undefined) return 1;\n if (!/^\\d{1,5}$/.test(raw)) return null;\n const page = Number(raw);\n return page >= 1 ? page : null;\n}\n\nfunction parseResourceNumber(raw: string | undefined): number | null {\n if (raw === undefined || !/^\\d{1,10}$/.test(raw)) return null;\n const parsed = Number(raw);\n return parsed > 0 ? parsed : null;\n}\n\nconst VALID_ISSUE_LABEL_FILTERS = new Set(['status: auto-triaged', 'status: needs approval']);\n\nfunction parseIssueLabelFilter(raw: string | undefined): string | undefined | null {\n if (raw === undefined || raw === '') return undefined;\n if (VALID_ISSUE_LABEL_FILTERS.has(raw)) return raw;\n return null;\n}\n\ninterface ResolvedProjectRepository extends ProjectRepository {\n connection: ProjectSourceControlConnection;\n installation: SourceControlInstallation;\n repository: SourceControlRepository;\n factoryProjectId: string;\n defaultBranch: string;\n}\n\nasync function resolveProjectRepository(args: {\n github: GithubIntegration;\n orgId: string;\n projectRepositoryId: string;\n}): Promise<ResolvedProjectRepository | null> {\n const projectRepository = await args.github.sourceControlStorage.projectRepositories.get({\n orgId: args.orgId,\n id: args.projectRepositoryId,\n });\n if (!projectRepository) return null;\n const connection = await args.github.sourceControlStorage.connections.get({\n orgId: args.orgId,\n id: projectRepository.connectionId,\n });\n if (!connection) return null;\n const repository = await args.github.sourceControlStorage.repositories.get({\n orgId: args.orgId,\n id: projectRepository.repositoryId,\n });\n if (!repository) return null;\n const installation = await args.github.sourceControlStorage.installations.get({\n orgId: args.orgId,\n id: connection.installationId,\n });\n if (!installation) return null;\n return {\n ...projectRepository,\n connection,\n installation,\n repository,\n factoryProjectId: connection.factoryProjectId,\n defaultBranch: projectRepository.branch ?? repository.defaultBranch,\n };\n}\n\nfunction polledIssueEvent(\n project: ResolvedProjectRepository,\n issue: {\n number: number;\n title: string;\n url: string;\n author: string | null;\n assignee: string | null;\n assignees?: string[];\n labels: string[];\n createdAt: string;\n },\n): ParsedGithubWebhook {\n const repositoryId = Number(project.repository.externalId);\n const assigneeLogins = issue.assignees ?? (issue.assignee ? [issue.assignee] : []);\n return {\n event: 'issues',\n deliveryId: `poll:${repositoryId}:issue:${issue.number}:${issue.createdAt}`,\n payload: {\n action: 'opened',\n installation: { id: Number(project.installation.externalId) },\n repository: { id: repositoryId, full_name: project.repository.slug },\n sender: { login: issue.author ?? '__unknown__' },\n issue: {\n number: issue.number,\n title: issue.title,\n html_url: issue.url,\n created_at: issue.createdAt,\n assignees: assigneeLogins.map(login => ({ login })),\n labels: issue.labels.map(name => ({ name })),\n },\n },\n };\n}\n\nfunction polledPullRequestEvent(\n project: ResolvedProjectRepository,\n pullRequest: {\n number: number;\n title: string;\n url: string;\n author: string | null;\n assignees: string[];\n requestedReviewers: string[];\n headBranch: string;\n baseBranch: string;\n createdAt: string;\n },\n): ParsedGithubWebhook {\n const repositoryId = Number(project.repository.externalId);\n return {\n event: 'pull_request',\n deliveryId: `poll:${repositoryId}:pull-request:${pullRequest.number}:${pullRequest.createdAt}`,\n payload: {\n action: 'opened',\n installation: { id: Number(project.installation.externalId) },\n repository: { id: repositoryId, full_name: project.repository.slug },\n sender: { login: pullRequest.author ?? '__unknown__' },\n pull_request: {\n number: pullRequest.number,\n title: pullRequest.title,\n html_url: pullRequest.url,\n created_at: pullRequest.createdAt,\n state: 'open',\n merged: false,\n assignees: pullRequest.assignees.map(login => ({ login })),\n requested_reviewers: pullRequest.requestedReviewers.map(login => ({ login })),\n head: { ref: pullRequest.headBranch },\n base: { ref: pullRequest.baseBranch },\n },\n },\n };\n}\n\nasync function ingestPolledEvents(\n events: ParsedGithubWebhook[],\n ingestFactoryEvent: MountGithubRoutesOptions['ingestFactoryEvent'],\n): Promise<void> {\n if (!ingestFactoryEvent) return;\n const results = await Promise.allSettled(events.map(event => ingestFactoryEvent(event)));\n const rejected = results.find((result): result is PromiseRejectedResult => result.status === 'rejected');\n if (rejected) throw rejected.reason;\n}\n\n/**\n * Build the GitHub routes as Mastra `apiRoutes`. When the feature is disabled,\n * returns only the `status` route so the SPA can detect the disabled state.\n */\nexport function buildGithubRoutes(options: MountGithubRoutesOptions): ApiRoute[] {\n const routes: ApiRoute[] = [];\n const {\n auth,\n sandbox,\n users,\n storage,\n github,\n stateSigner,\n controller,\n memorySettings,\n emitAudit,\n sessionRetirement,\n workItems,\n } = options;\n const diagnostics = () =>\n getGithubFeatureDiagnostics({ github, auth, appDbConfigured: storage !== undefined, stateSigner, sandbox });\n\n // The status route is always registered so the SPA can detect the disabled state.\n routes.push(\n registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n if (!isGithubFeatureEnabled({ github, auth }) || !github || !stateSigner) {\n return c.json({\n enabled: false,\n connected: false,\n installations: [],\n reason: 'missing_config',\n diagnostics: diagnostics(),\n });\n }\n // Resolve the session from the request cookie: on platform deploys custom\n // apiRoutes run on an isolated context where the gate's stash is invisible.\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\n // Org-scoped: personal (no-org) users have GitHub projects disabled. Report\n // enabled (so the SPA can show the org-required hint) but never connected.\n if (!tenant.orgId) {\n return c.json({\n enabled: true,\n sandboxEnabled: !!sandbox,\n organizationRequired: true,\n connected: false,\n installations: [],\n reason: 'organization_required',\n diagnostics: diagnostics(),\n });\n }\n\n const rows = options.github\n ? await options.github.sourceControlStorage.installations.list({ orgId: tenant.orgId })\n : [];\n\n const connected = rows.length > 0;\n return c.json({\n enabled: true,\n sandboxEnabled: !!sandbox,\n connected,\n installations: rows.map(r => ({\n installationId: Number(r.externalId),\n accountLogin: r.accountName,\n accountType: r.accountType,\n })),\n reason: connected ? 'ready' : 'not_connected',\n diagnostics: diagnostics(),\n });\n },\n }),\n );\n\n // Without an integration instance + state signer there is nothing the\n // remaining handlers can do — serve only the disabled `status` route\n // (mirrors the feature gate).\n if (!isGithubFeatureEnabled({ github, auth }) || !github || !stateSigner) {\n return routes;\n }\n const signState = (orgId: string, userId: string): string => stateSigner.sign(orgId, userId);\n const verifyState = (state: string | undefined) => stateSigner.verify(state);\n\n routes.push(\n registerApiRoute('/web/github/subscriptions', {\n method: 'GET',\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 const resourceId = c.req.query('resourceId');\n const threadId = c.req.query('threadId');\n const sessionScope = c.req.query('scope');\n if (!resourceId || !threadId) return c.json({ error: 'resourceId and threadId are required' }, 400);\n\n const subscriptions = await listPullRequestSubscriptionsForThread(\n {\n orgId: tenant.orgId,\n resourceId,\n threadId,\n sessionScope,\n },\n github.integrationStorage,\n );\n return c.json({\n subscriptions: subscriptions.map(subscription => ({\n id: subscription.id,\n repoFullName: subscription.data.repositorySlug,\n pullRequestNumber: Number(subscription.data.changeRequestId),\n status: subscription.status,\n url: `https://github.com/${subscription.data.repositorySlug}/pull/${subscription.data.changeRequestId}`,\n })),\n });\n },\n }),\n registerApiRoute('/web/github/webhook', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const result = await handleGithubWebhook(loose(c), {\n github,\n ingestFactoryEvent: options.ingestFactoryEvent,\n ...(options.controller\n ? {\n controller: options.controller,\n onTargetError: (subscription, error) => {\n console.warn(\n `[GitHub 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\n const redirectUri = options.redirectUri ?? `${(options.baseUrl ?? '').replace(/\\/$/, '')}/auth/github/callback`;\n\n // ── Connect: bounce through the OAuth identify flow ─────────────────────\n // Identify-first (rather than install-first) so an app that is *already*\n // installed on the org re-syncs into our DB: GitHub's install page dead-ends\n // on the installation settings screen for existing installs and never\n // redirects back to us. The callback persists whatever installations the\n // verified user token can see, and only redirects to the install URL when\n // there are none.\n //\n // `?manage=1` skips the identify bounce and sends the user straight to\n // GitHub's installation page — used by \"Manage GitHub connection\" to\n // add/remove accounts and repo access. For an already-authorized user the\n // identify flow completes instantly and invisibly, so without this the\n // manage button would appear to do nothing. GitHub's post-install \"Save\"\n // redirect lands back on the callback, which re-syncs installations.\n routes.push(\n registerApiRoute('/auth/github/connect', {\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 state = signState(resolved.tenant.orgId, resolved.tenant.userId);\n if (c.req.query('manage')) return c.redirect(github.buildInstallUrl(state));\n return c.redirect(github.buildOAuthIdentifyUrl(state, redirectUri));\n },\n }),\n );\n\n // ── Callback: confirm identity, persist the installation against the org ──\n routes.push(\n registerApiRoute('/auth/github/callback', {\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 { orgId, userId } = resolved.tenant;\n\n const state = c.req.query('state');\n if (!state) {\n // GitHub's \"Save\"/update redirect from the installation settings page\n // arrives with `installation_id` + `setup_action` but no state. We\n // never trust the raw installation_id; start a fresh identify bounce\n // bound to the current session so the update re-syncs installations.\n return c.redirect(github.buildOAuthIdentifyUrl(signState(orgId, userId), redirectUri));\n }\n const stateTenant = verifyState(state);\n if (!stateTenant || stateTenant.userId !== userId || stateTenant.orgId !== orgId) {\n // CSRF / cross-user/org linking protection: the signed state must belong\n // to the same logged-in user *and* their current org.\n console.warn(\n '[GitHub] Install callback rejected: state/tenant mismatch.',\n JSON.stringify({\n stateValid: Boolean(stateTenant),\n stateOrgId: stateTenant?.orgId,\n stateUserId: stateTenant?.userId,\n sessionOrgId: orgId,\n sessionUserId: userId,\n }),\n );\n return c.redirect('/?github=error');\n }\n\n const code = c.req.query('code');\n // We only ever persist installations that GitHub confirms belong to *this*\n // user via the OAuth code path. The raw `installation_id` from the install\n // redirect is not trusted on its own — anyone with a valid state could pass\n // an arbitrary id — so when no code is present we bounce through the OAuth\n // identify flow to obtain a verified user token first.\n if (!code) {\n return c.redirect(github.buildOAuthIdentifyUrl(signState(orgId, userId), redirectUri));\n }\n\n try {\n const userToken = await github.exchangeOAuthCode(code, redirectUri);\n const installations = await github.listUserInstallations(userToken);\n if (installations.length === 0) {\n // Verified user has no installations yet — send them to the actual\n // install page. After installing, GitHub redirects back here with\n // the same state (and no code), which bounces through identify\n // again and lands in the persist path below.\n return c.redirect(github.buildInstallUrl(signState(orgId, userId)));\n }\n for (const inst of installations) {\n // The installation is org-owned; `userId` records who connected it.\n await github.sourceControlStorage.installations.upsert({\n orgId,\n connectedByUserId: userId,\n externalId: inst.installationId.toString(),\n accountName: inst.accountLogin,\n accountType: inst.accountType,\n });\n }\n } catch (error) {\n console.warn(\n `[GitHub] Install callback failed to persist installations for org ${orgId} / user ${userId}.`,\n error,\n );\n return c.redirect('/?github=error');\n }\n\n return c.redirect('/?github=connected');\n },\n }),\n );\n\n // ── List repos across the org's installations ───────────────────────────\n routes.push(\n registerApiRoute('/web/github/repos', {\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\n const orgId = resolved.tenant.orgId;\n const installs = await github.sourceControlStorage.installations.list({ orgId });\n\n const query = (c.req.query('q') ?? '').toLowerCase();\n // List every installation's repositories in parallel — installations\n // are independent upstream calls, and serial listing multiplied\n // worst-case latency by installation count.\n const listed = await Promise.all(\n installs.map(async inst => {\n try {\n return { inst, list: await github.listInstallationRepos(Number(inst.externalId)) };\n } catch (err) {\n // GitHub 404s when the installation no longer exists for this app\n // (app uninstalled/reinstalled, or the row was recorded under\n // different app credentials). Prune the stale row so `/status`\n // reflects reality and the UI prompts a reconnect, then keep\n // listing the remaining installations.\n if ((err as { status?: number }).status !== 404) throw err;\n console.error(`[Mastra Factory] pruning stale GitHub installation ${inst.externalId} (404 from GitHub)`);\n await github.sourceControlStorage.installations.delete({ orgId, id: inst.id });\n return { inst, list: [] };\n }\n }),\n );\n\n // Filter + dedupe by repo id in installation order — same result\n // ordering as the previous serial loop.\n const matches = [];\n const seenRepositoryIds = new Set<number>();\n for (const { inst, list } of listed) {\n for (const repo of list) {\n if (query && !repo.fullName.toLowerCase().includes(query)) continue;\n if (seenRepositoryIds.has(repo.id)) continue;\n seenRepositoryIds.add(repo.id);\n matches.push({ inst, repo });\n }\n }\n\n const repos = matches.map(({ inst, repo }) => ({\n ...repo,\n installationStorageId: inst.id,\n sandboxProvider: sandbox ? 'custom' : 'none',\n // Display only — the runtime workdir is resolved from the\n // live sandbox at open time. Repositories are persisted only after\n // selection, so `~/<repo>` is the honest listing-time guess.\n sandboxWorkdir: `~/${sanitizeSegment(repo.fullName.split('/', 2)[1] || 'repo')}`,\n }));\n return c.json({ repos });\n },\n }),\n );\n\n // ── List a project's open GitHub issues ──────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/issues', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const page = parseListPage(c.req.query('page'));\n if (page === null) return c.json({ error: 'invalid_page' }, 400);\n const label = parseIssueLabelFilter(c.req.query('label'));\n if (label === null) return c.json({ error: 'invalid_label' }, 400);\n try {\n const { issues, nextCursor } = await github.intake.listIssues({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceIds: [loaded.project.repository.slug],\n labels: label ? [label] : undefined,\n cursor: String(page),\n });\n const responseIssues = issues.map(issue => ({\n number: Number(issue.id),\n title: issue.title,\n url: issue.url,\n author: issue.author,\n assignee: issue.assignee,\n assignees: issue.assignees,\n labels: issue.labels,\n comments: issue.commentCount ?? 0,\n createdAt: issue.createdAt,\n updatedAt: issue.updatedAt,\n }));\n await ingestPolledEvents(\n responseIssues.map(issue => polledIssueEvent(loaded.project, issue)),\n options.ingestFactoryEvent,\n );\n return c.json({\n issues: responseIssues,\n nextPage: nextCursor === null ? null : Number(nextCursor),\n });\n } catch (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n routes.push(\n registerApiRoute('/web/github/projects/:id/issues/:number', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const number = parseResourceNumber(c.req.param('number'));\n if (number === null) return c.json({ error: 'invalid_number' }, 400);\n try {\n const detail = await github.intake.getIssue({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceId: loaded.project.repository.slug,\n issueId: String(number),\n });\n if (detail === null) return c.json({ error: 'issue_not_found' }, 404);\n return c.json({\n number: Number(detail.id),\n title: detail.title,\n url: detail.url,\n author: detail.author,\n assignee: detail.assignee,\n labels: detail.labels,\n comments: detail.commentCount ?? 0,\n createdAt: detail.createdAt,\n updatedAt: detail.updatedAt,\n description: detail.description,\n });\n } catch (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n // ── List a project's open (non-draft) pull requests ─────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/prs', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const page = parseListPage(c.req.query('page'));\n if (page === null) return c.json({ error: 'invalid_page' }, 400);\n try {\n const { pullRequests, nextCursor } = await github.versionControl.listPullRequests({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceId: loaded.project.repository.slug,\n includeDrafts: false,\n cursor: String(page),\n });\n const responsePullRequests = pullRequests.map(pr => ({\n number: Number(pr.id),\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 }));\n await ingestPolledEvents(\n responsePullRequests.map(pullRequest => polledPullRequestEvent(loaded.project, pullRequest)),\n options.ingestFactoryEvent,\n );\n return c.json({\n pullRequests: responsePullRequests,\n nextPage: nextCursor === null ? null : Number(nextCursor),\n });\n } catch (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n routes.push(\n registerApiRoute('/web/github/projects/:id/prs/:number', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const number = parseResourceNumber(c.req.param('number'));\n if (number === null) return c.json({ error: 'invalid_number' }, 400);\n try {\n const pr = await github.versionControl.getPullRequest({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceId: loaded.project.repository.slug,\n pullRequestId: String(number),\n });\n if (pr === null) return c.json({ error: 'pull_request_not_found' }, 404);\n return c.json({\n number: Number(pr.id),\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 (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n // ── Read per-project settings ────────────────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/settings', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n return c.json({\n setupCommand: loaded.project.setupCommand,\n teardownCommand: loaded.project.teardownCommand,\n });\n },\n }),\n );\n\n // ── Update per-project settings ──────────────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/settings', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n\n let body: { setupCommand?: unknown; teardownCommand?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n\n const commands = ['setupCommand', 'teardownCommand'] as const;\n for (const command of commands) {\n const value = body[command];\n if (value === undefined) continue;\n if (value !== null && typeof value !== 'string') {\n return c.json({ error: `Invalid ${command}` }, 400);\n }\n if (typeof value === 'string' && value.length > 2000) {\n return c.json({ error: `${command} too long (max 2000 characters)` }, 400);\n }\n // Reject control characters (except newline/tab). Commands are shell\n // scripts by design, but escape sequences and NULs can spoof logs or\n // confuse the sandbox shell.\n if (typeof value === 'string' && /[\\0-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/.test(value)) {\n return c.json({ error: `${command} contains control characters` }, 400);\n }\n }\n\n const normalizeCommand = (value: unknown): string | null | undefined => {\n if (value === undefined) return undefined;\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;\n };\n const setupCommand = normalizeCommand(body.setupCommand);\n const teardownCommand = normalizeCommand(body.teardownCommand);\n\n await github.sourceControlStorage.projectRepositories.update({\n orgId: loaded.project.installation.orgId,\n id: loaded.project.id,\n input: {\n ...(setupCommand !== undefined ? { setupCommand } : {}),\n ...(teardownCommand !== undefined ? { teardownCommand } : {}),\n },\n });\n return c.json({\n setupCommand: setupCommand === undefined ? loaded.project.setupCommand : setupCommand,\n teardownCommand: teardownCommand === undefined ? loaded.project.teardownCommand : teardownCommand,\n });\n },\n }),\n );\n\n // ── Org GitHub PATs ──────────────────────────────────────────────────────\n // Installation tokens are the wrong credential for the `gh` CLI (integration\n // -restricted endpoints 403 regardless of permissions), so orgs paste\n // classic PATs the sandboxes use instead: a `default` worker token, and an\n // optional `reviewer` token that review-board sessions use so PR reviews\n // come from a different account. Tokens are never sent back to the browser —\n // only whether each is configured.\n const parsePatKind = (value: unknown): GithubPatKind | null => {\n if (value === undefined || value === null || value === 'default') return 'default';\n if (value === 'reviewer') return 'reviewer';\n return null;\n };\n routes.push(\n registerApiRoute('/web/github/pat', {\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 return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n registerApiRoute('/web/github/pat', {\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\n let body: { token?: unknown; kind?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const kind = parsePatKind(body.kind);\n if (!kind) return c.json({ error: \"kind must be 'default' or 'reviewer'\" }, 400);\n const token = typeof body.token === 'string' ? body.token.trim() : '';\n if (!token) return c.json({ error: 'A token is required' }, 400);\n if (token.length > 500) return c.json({ error: 'Token too long (max 500 characters)' }, 400);\n if (/\\s/.test(token)) return c.json({ error: 'Token must not contain whitespace' }, 400);\n\n await setGithubPat(github.integrationStorage, resolved.tenant.orgId, token, kind);\n return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n registerApiRoute('/web/github/pat', {\n method: 'DELETE',\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 kind = parsePatKind(c.req.query('kind'));\n if (!kind) return c.json({ error: \"kind must be 'default' or 'reviewer'\" }, 400);\n await clearGithubPat(github.integrationStorage, resolved.tenant.orgId, kind);\n return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n );\n\n // ── Sessions / commit / push / PR ────────────────────────────────────────\n routes.push(\n ...buildProjectGitRoutes({\n github,\n auth,\n sandbox,\n users,\n controller,\n memorySettings,\n emitAudit,\n sessionRetirement,\n workItems,\n }),\n );\n\n return routes;\n}\n\n/**\n * Load the org-owned project for a read-only GitHub API route. Unlike\n * `loadOwnedProject`, this never touches sandbox state — the issues/PR list\n * routes only need the repo + installation, so they work before a sandbox is\n * ever provisioned.\n */\nasync function loadOrgProject(options: {\n github: GithubIntegration;\n auth: RouteAuth;\n c: RouteContext;\n}): Promise<{ project: ResolvedProjectRepository; orgId: string; userId: string } | { response: Response }> {\n const { github, auth, c } = options;\n const resolved = await resolveOrgTenant(c, auth);\n if ('response' in resolved) return { response: resolved.response };\n const { orgId, userId } = resolved.tenant;\n\n const projectRepositoryId = c.req.param('id');\n if (!projectRepositoryId) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n const project = await resolveProjectRepository({ github, orgId, projectRepositoryId });\n if (!project) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n return { project, orgId, userId };\n}\n\n/** Derive a commit/author identity from the authenticated host user. */\nfunction identityFromUser(user: unknown): GitIdentity {\n const u = user as { name?: string; email?: string } | null | undefined;\n return { name: u?.name ?? null, email: u?.email ?? null };\n}\n\n/** Map a sandbox/setup-command error to an actionable HTTP response. */\nfunction gitErrorResponse(c: Context, err: unknown) {\n if (err instanceof SetupCommandError) {\n return c.json({ error: err.code, message: err.message }, 502);\n }\n if (err instanceof MaterializeError) {\n return c.json({ error: err.code, message: err.message }, 502);\n }\n return c.json({ error: 'git_failed', message: err instanceof Error ? err.message : String(err) }, 500);\n}\n\n/**\n * Load the org-owned project for a git route. Centralizes the auth +\n * org/ownership checks every git route shares: the project is scoped by\n * `(id, orgId)`. Returns the tenant and project, or a ready-to-return error\n * response.\n */\nasync function loadOwnedProject(options: {\n github: GithubIntegration;\n auth: RouteAuth;\n sandbox?: MastraFactorySandboxConfig;\n c: RouteContext;\n}): Promise<{ orgId: string; userId: string; project: ResolvedProjectRepository } | { response: Response }> {\n const { github, auth, sandbox, c } = options;\n const resolved = await resolveOrgTenant(c, auth);\n if ('response' in resolved) return { response: resolved.response };\n const { orgId, userId } = resolved.tenant;\n\n if (!sandbox) {\n return {\n response: c.json({ error: 'sandbox_not_configured', message: 'No sandbox provider is configured.' }, 503),\n };\n }\n\n const projectRepositoryId = c.req.param('id');\n if (!projectRepositoryId) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n const project = await resolveProjectRepository({ github, orgId, projectRepositoryId });\n if (!project) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n return { orgId, userId, project };\n}\n\n/**\n * One naming per session at a time: a second caller joins the run already in\n * flight instead of paying for another model call and racing its rename.\n */\nfunction createSessionNaming() {\n const inFlight = new Map<string, Promise<string | null>>();\n return (sessionId: string, run: () => Promise<string | null>) => {\n const pending = inFlight.get(sessionId);\n if (pending) return pending;\n const started = run().finally(() => inFlight.delete(sessionId));\n inFlight.set(sessionId, started);\n return started;\n };\n}\n\n/**\n * Name a thread with a stored model id. Resolution has to go through\n * mastracode's gateway: a bare id handed to core's model router looks for a\n * process env key instead of the caller's stored provider credentials.\n */\nfunction titleModel(modelId: string) {\n return ({ requestContext }: { requestContext: RequestContext }) =>\n resolveModel(modelId, { remapForCodexOAuth: true, requestContext });\n}\n\ninterface SessionOwnerProfile {\n id: string;\n name: string;\n avatarUrl?: string;\n}\n\ntype SessionOwnerUserProvider = Pick<IUserProvider, 'getUser'> & Partial<Pick<IUserProvider, 'getUsers'>>;\n\n/** A screenful of history; GitHub caps its own page at 100. */\nconst DEFAULT_COMMIT_PAGE = 20;\nconst MAX_COMMIT_PAGE = 100;\n\nconst MAX_SESSION_OWNER_PROFILES = 100;\nconst MAX_SESSION_OWNER_PROFILE_CACHE_ENTRIES = 500;\nconst SESSION_OWNER_PROFILE_TTL_MS = 5 * 60_000;\n\nfunction createSessionOwnerProfileResolver(users: SessionOwnerUserProvider | undefined) {\n const cache = new Map<string, { profile?: SessionOwnerProfile; expiresAt: number }>();\n const cacheProfile = (userId: string, profile: SessionOwnerProfile | undefined, expiresAt: number) => {\n cache.delete(userId);\n cache.set(userId, { profile, expiresAt });\n if (cache.size > MAX_SESSION_OWNER_PROFILE_CACHE_ENTRIES) {\n const oldestUserId = cache.keys().next().value;\n if (oldestUserId !== undefined) cache.delete(oldestUserId);\n }\n };\n\n return async (userIds: string[]): Promise<Map<string, SessionOwnerProfile>> => {\n if (!users) return new Map();\n\n const requestedUserIds = [...new Set(userIds)].slice(0, MAX_SESSION_OWNER_PROFILES);\n const profiles = new Map<string, SessionOwnerProfile>();\n const unresolvedUserIds: string[] = [];\n const now = Date.now();\n\n for (const userId of requestedUserIds) {\n const cached = cache.get(userId);\n if (!cached || cached.expiresAt <= now) {\n cache.delete(userId);\n unresolvedUserIds.push(userId);\n } else if (cached.profile) {\n profiles.set(userId, cached.profile);\n }\n }\n\n if (unresolvedUserIds.length === 0) return profiles;\n\n let resolvedUsers: Array<Awaited<ReturnType<SessionOwnerUserProvider['getUser']>>>;\n if (users.getUsers) {\n try {\n resolvedUsers = await users.getUsers(unresolvedUserIds);\n } catch (error) {\n console.warn('[GitHub Sessions] Bulk session owner profile lookup failed; falling back to individual lookups', {\n error: error instanceof Error ? error.message : String(error),\n });\n resolvedUsers = (await Promise.allSettled(unresolvedUserIds.map(userId => users.getUser(userId))))\n .filter(result => result.status === 'fulfilled')\n .map(result => result.value);\n }\n } else {\n resolvedUsers = (await Promise.allSettled(unresolvedUserIds.map(userId => users.getUser(userId))))\n .filter(result => result.status === 'fulfilled')\n .map(result => result.value);\n }\n\n for (const user of resolvedUsers) {\n if (!user) continue;\n const name = user.name?.trim() || user.email?.trim();\n if (!name) continue;\n profiles.set(user.id, {\n id: user.id,\n name,\n ...(user.avatarUrl ? { avatarUrl: user.avatarUrl } : {}),\n });\n }\n\n const expiresAt = now + SESSION_OWNER_PROFILE_TTL_MS;\n for (const userId of unresolvedUserIds) {\n cacheProfile(userId, profiles.get(userId), expiresAt);\n }\n return profiles;\n };\n}\n\nfunction buildProjectGitRoutes({\n github,\n auth,\n sandbox,\n users,\n controller,\n memorySettings,\n emitAudit,\n sessionRetirement,\n workItems,\n}: {\n github: GithubIntegration;\n auth: RouteAuth;\n sandbox?: MastraFactorySandboxConfig;\n users?: SessionOwnerUserProvider;\n controller?: MountedMastraCode['controller'];\n memorySettings: MountGithubRoutesOptions['memorySettings'];\n emitAudit?: AuditEmitter['emit'];\n sessionRetirement?: MountGithubRoutesOptions['sessionRetirement'];\n workItems?: MountGithubRoutesOptions['workItems'];\n}): ApiRoute[] {\n const nameSession = createSessionNaming();\n const resolveSessionOwnerProfiles = createSessionOwnerProfileResolver(users);\n return [\n // ── Create / list Factory sessions ──────────────────────────────────────\n registerApiRoute('/web/github/projects/:id/sessions', {\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 { orgId, userId } = resolved.tenant;\n const projectRepositoryId = c.req.param('id');\n const project = projectRepositoryId\n ? await resolveProjectRepository({ github, orgId, projectRepositoryId })\n : null;\n if (!project) return c.json({ error: 'Project repository not found' }, 404);\n const sessions = await github.sourceControlStorage.sessions.list({\n projectRepositoryId: project.id,\n viewerUserId: userId,\n });\n const owners = await resolveSessionOwnerProfiles(sessions.map(session => session.userId));\n return c.json({\n sessions: sessions.map(session => {\n const owner = owners.get(session.userId);\n return { ...session, ...(owner ? { owner } : {}) };\n }),\n });\n },\n }),\n registerApiRoute('/web/github/projects/:id/sessions', {\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 { orgId, userId } = resolved.tenant;\n const projectRepositoryId = c.req.param('id');\n const project = projectRepositoryId\n ? await resolveProjectRepository({ github, orgId, projectRepositoryId })\n : null;\n if (!project) return c.json({ error: 'Project repository not found' }, 404);\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isJsonObject(body)) return c.json({ error: 'Invalid JSON body' }, 400);\n const requestedBaseBranch = body.baseBranch;\n if (requestedBaseBranch !== undefined && typeof requestedBaseBranch !== 'string') {\n return c.json({ error: 'Invalid baseBranch' }, 400);\n }\n const baseBranch = requestedBaseBranch ?? project.defaultBranch;\n if (!isValidGitRefSandbox(baseBranch)) return c.json({ error: 'Invalid baseBranch' }, 400);\n\n const requestedSessionId = body.sessionId;\n if (\n requestedSessionId !== undefined &&\n (typeof requestedSessionId !== 'string' || !UUID_PATTERN.test(requestedSessionId))\n ) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n const sessionId = requestedSessionId ?? randomUUID();\n\n const requestedTitle = body.title;\n if (requestedTitle !== undefined && typeof requestedTitle !== 'string') {\n return c.json({ error: 'Invalid title' }, 400);\n }\n const normalizedTitle = requestedTitle === undefined ? null : normalizeSessionTitle(requestedTitle);\n\n const requestedBranch = body.branch;\n let branch: string;\n if (requestedBranch === undefined) {\n branch = `${USER_SESSION_BRANCH_PREFIX}${sessionId}`;\n } else if (typeof requestedBranch === 'string' && isValidGitRefSandbox(requestedBranch)) {\n branch = requestedBranch;\n } else {\n return c.json({ error: 'Invalid branch' }, 400);\n }\n\n if (requestedSessionId !== undefined) {\n const existing = await github.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (existing) {\n if (\n existing.projectRepositoryId !== project.id ||\n existing.orgId !== orgId ||\n existing.userId !== userId ||\n existing.branch !== branch\n ) {\n return c.json({ error: 'Session ID conflict' }, 409);\n }\n return c.json({ session: existing });\n }\n }\n\n const session = await github.sourceControlStorage.sessions\n .create({\n sessionId,\n projectRepositoryId: project.id,\n orgId,\n userId,\n branch,\n baseBranch,\n title: normalizedTitle,\n visibility: 'org',\n })\n .catch(async error => {\n if (!(error instanceof UniqueViolationError) || requestedSessionId === undefined) throw error;\n const conflict = await github.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (!conflict) throw error;\n return conflict;\n });\n if (\n requestedSessionId !== undefined &&\n (session.sessionId !== sessionId ||\n session.projectRepositoryId !== project.id ||\n session.orgId !== orgId ||\n session.userId !== userId ||\n session.branch !== branch)\n ) {\n return c.json({ error: 'Session ID conflict' }, 409);\n }\n return c.json({ session });\n },\n }),\n registerApiRoute('/web/user-sessions/:sessionId', {\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 session = await github.sourceControlStorage.sessions.getBySessionId(c.req.param('sessionId'));\n // Private sessions 404 (not 403) for non-owners so their IDs do not\n // leak existence; the body must match the genuinely-missing case.\n if (\n !session ||\n session.orgId !== resolved.tenant.orgId ||\n (session.visibility === 'private' && session.userId !== resolved.tenant.userId)\n ) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json({ session });\n },\n }),\n registerApiRoute('/web/user-sessions/:sessionId', {\n method: 'DELETE',\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 session = await github.sourceControlStorage.sessions.getBySessionId(c.req.param('sessionId'));\n if (!session || session.orgId !== resolved.tenant.orgId || session.userId !== resolved.tenant.userId) {\n return c.json({ error: 'Session not found' }, 404);\n }\n try {\n await controller?.deleteSession({ resourceId: session.sessionId });\n } catch (error) {\n console.error('[GitHub Sessions] Failed to tear down live controller session', {\n sessionId: session.sessionId,\n error,\n });\n }\n if (sessionRetirement) {\n await sessionRetirement.retireSession({\n sourceControl: github.sourceControlStorage,\n ...(workItems ? { workItems } : {}),\n orgId: session.orgId,\n sessionId: session.sessionId,\n deleteSession: true,\n });\n } else {\n await workItems?.clearSessionReferences({ orgId: session.orgId, sessionId: session.sessionId });\n await github.sourceControlStorage.sessions.delete(session.id);\n void reclaimDeletedSessionSandbox({ session }).catch((error: unknown) => {\n console.error('[GitHub Sessions] Failed to reclaim sandbox for deleted session', {\n sessionId: session.sessionId,\n sandboxId: session.sandboxId,\n error,\n });\n });\n }\n return c.json({ removed: true });\n },\n }),\n\n // ── Re-name a session's thread with the title model ────────────────────\n registerApiRoute('/web/user-sessions/:sessionId/title', {\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 sessionId = c.req.param('sessionId');\n const row = await github.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (!row || row.orgId !== resolved.tenant.orgId || row.userId !== resolved.tenant.userId) {\n return c.json({ error: 'Session not found' }, 404);\n }\n if (!controller) return c.json({ error: 'Sessions are not available on this server.' }, 503);\n\n const threads = await controller.queryThreads({ resourceId: sessionId });\n const thread = threads.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())[0];\n if (!thread) return c.json({ error: 'This session has no conversation to name yet.' }, 409);\n\n // A session that is not live carries neither the observer model that names\n // its threads nor the identity whose provider credentials pay for it.\n const stored = await memorySettings.get({ orgId: row.orgId, userId: row.userId });\n const requestContext = new RequestContext();\n requestContext.set('user', { workosId: row.userId, organizationId: row.orgId });\n\n try {\n const title = await nameSession(sessionId, async () => {\n const generated = await controller.generateThreadTitle({\n threadId: thread.id,\n resourceId: sessionId,\n requestContext,\n ...(stored?.observerModelId ? { model: titleModel(stored.observerModelId) } : {}),\n });\n const named = generated ? normalizeSessionTitle(generated) : null;\n if (named) await github.sourceControlStorage.sessions.rename({ sessionId, title: named });\n return named;\n });\n if (!title) return c.json({ error: 'The model returned an empty title. Try again.' }, 502);\n return c.json({ title });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Stage all + commit inside a Factory session workspace ──────────────\n registerApiRoute('/web/github/projects/:id/commit', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, sandbox, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { userId, project } = owned;\n\n let body: { message?: unknown; sessionId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (typeof body.message !== 'string' || body.message.trim().length === 0 || body.message.length > 5000) {\n return c.json({ error: 'Invalid message' }, 400);\n }\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n const { workdir, sandbox: sessionSandbox } = sessionWorkspace;\n\n try {\n return await withSessionOperationLock(sessionWorkspace.session.sessionId, async () => {\n const result = await commitAll(\n sessionSandbox,\n workdir,\n body.message as string,\n identityFromUser(await auth.ensureUser(loose(c))),\n );\n if (result.committed) {\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.commit',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'session', id: sessionWorkspace.session.sessionId }],\n metadata: { sessionId: sessionWorkspace.session.sessionId },\n },\n });\n }\n return c.json({ committed: result.committed });\n });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n\n // ── Recent commits on a repository branch ───────────────────────────────\n registerApiRoute('/web/github/projects/:id/commits', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const { orgId, project } = loaded;\n\n const branch = c.req.query('branch') ?? project.defaultBranch;\n if (!isValidGitRefSandbox(branch)) return c.json({ error: 'Invalid branch' }, 400);\n // GitHub takes `per_page` as an integer, so a fractional limit would go out verbatim.\n const limit = Math.min(\n Math.max(Math.floor(Number(c.req.query('limit') ?? DEFAULT_COMMIT_PAGE)) || DEFAULT_COMMIT_PAGE, 1),\n MAX_COMMIT_PAGE,\n );\n\n try {\n const commits = await listRepositoryCommits(github, { orgId, project, branch, limit });\n return c.json({ commits, branch });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n\n // ── Push a branch back to GitHub ────────────────────────────────────────\n registerApiRoute('/web/github/projects/:id/push', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, sandbox, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { orgId, userId, project } = owned;\n\n let body: { branch?: unknown; sessionId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isValidGitRefSandbox(body.branch)) {\n return c.json({ error: 'Invalid branch' }, 400);\n }\n const branch = body.branch;\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n const { workdir, sandbox: sessionSandbox } = sessionWorkspace;\n\n try {\n return await withSessionOperationLock(sessionWorkspace.session.sessionId, async () => {\n const access = await github.versionControl.getRepositoryAccess({\n orgId,\n repositoryId: project.repository.id,\n });\n if (!access.authorization) throw new Error('Repository access did not include a bearer token.');\n await pushBranch(sessionSandbox, workdir, branch, access.authorization.token, project.repository.slug);\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.push',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'branch', id: branch }],\n metadata: { branch, sessionId: sessionWorkspace.session.sessionId },\n },\n });\n return c.json({ pushed: true, branch });\n });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n\n // ── Open a pull request through the version-control capability ─────────\n registerApiRoute('/web/github/projects/:id/pr', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, sandbox, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { orgId, userId, project } = owned;\n\n let body: {\n branch?: unknown;\n base?: unknown;\n title?: unknown;\n body?: unknown;\n sessionId?: unknown;\n };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isValidGitRefSandbox(body.branch)) {\n return c.json({ error: 'Invalid branch' }, 400);\n }\n const base = body.base === undefined ? project.defaultBranch : body.base;\n if (!isValidGitRefSandbox(base)) {\n return c.json({ error: 'Invalid base' }, 400);\n }\n if (typeof body.title !== 'string' || body.title.trim().length === 0 || body.title.length > 256) {\n return c.json({ error: 'Invalid title' }, 400);\n }\n if (body.body !== undefined && (typeof body.body !== 'string' || body.body.length > 65536)) {\n return c.json({ error: 'Invalid body' }, 400);\n }\n const head = body.branch;\n const title = body.title;\n const prBody = body.body as string | undefined;\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n\n try {\n return await withSessionOperationLock(sessionWorkspace.session.sessionId, async () => {\n const result = await github.versionControl.createPullRequest({\n connection: {\n type: 'app-installation',\n installationId: Number(project.installation.externalId),\n },\n sourceId: project.repository.slug,\n baseBranch: base,\n headBranch: head,\n title,\n body: prBody,\n actingUserId: userId,\n });\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.pr_opened',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'pull_request', id: result.url, name: title }],\n metadata: { branch: head, base, url: result.url },\n },\n });\n const pullRequestNumber = pullRequestNumberFromUrl(result.url, project.repository.slug);\n if (pullRequestNumber) {\n const sessionId = sessionWorkspace.session.sessionId;\n await subscribeToPullRequest(\n {\n orgId,\n installationExternalId: project.installation.externalId,\n projectRepositoryId: project.id,\n repositoryExternalId: project.repository.externalId,\n repositorySlug: project.repository.slug,\n changeRequestId: pullRequestNumber.toString(),\n sessionId,\n ownerId: userId,\n resourceId: sessionId,\n threadId: sessionId,\n source: 'factory-pr-create',\n subscribedByUserId: userId,\n },\n github.integrationStorage,\n ).catch((error: unknown) => {\n console.warn(\n `[GitHub] Pull request ${result.url} was created but automatic subscription failed.`,\n error,\n );\n });\n }\n return c.json({ url: result.url });\n });\n } catch (err) {\n return c.json(\n { error: 'github_pr_create_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n ];\n}\n\n/** Resolve the materialized workspace owned by a Factory session. */\nasync function resolveSessionWorkspace(\n github: GithubIntegration,\n projectId: string,\n userId: string,\n sessionId: unknown,\n) {\n if (typeof sessionId !== 'string') {\n return undefined;\n }\n const session = await github.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (session?.projectRepositoryId !== projectId || session.userId !== userId) {\n return undefined;\n }\n // Session sandboxes live in the per-process memo, keyed by the session row\n // id. Passive resolution only — git write routes never provision. An\n // unresolved workdir means the sandbox never started here: nothing is\n // materialized, so there is no workspace to operate on.\n const entry = peekSessionSandbox(session.id);\n if (!entry?.workdir) return undefined;\n return {\n session,\n workdir: entry.workdir,\n sandbox: requireExec(entry.sandbox),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"routes.js","names":["isValidGitRefSandbox"],"sources":["../../../src/integrations/github/routes.ts"],"sourcesContent":["/**\n * Mastra `apiRoutes` for the GitHub App project feature.\n *\n * Registered alongside the other `/web/*` routes, behind the host auth gate.\n * Every route additionally re-checks the authenticated user via the injected\n * `RouteAuth` seam and scopes all rows by that user's stable id, so a user can\n * only ever see and operate on their own installations and projects.\n *\n * When the feature is disabled (`isGithubFeatureEnabled()` false), `buildGithubRoutes`\n * returns only `GET /web/github/status`, which reports `enabled:false`\n * so the SPA can cleanly hide all GitHub UI.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { MountedMastraCode } from '@mastra/code-sdk';\nimport { resolveModel } from '@mastra/code-sdk/agents/model';\nimport { RequestContext } from '@mastra/core/request-context';\nimport type { ApiRoute, IUserProvider } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport { UniqueViolationError } from '@mastra/core/storage';\nimport type { FactoryStorage } from '@mastra/core/storage';\nimport type { Context } from 'hono';\nimport type { RouteAuth } from '../../routes/route.js';\nimport { AUTO_TRIAGED_LABEL, NEEDS_APPROVAL_LABEL } from '../../rules/types.js';\nimport { requireExec } from '../../sandbox/materialization.js';\nimport type { ExecutableSandbox } from '../../sandbox/materialization.js';\nimport type { MastraFactorySandboxConfig } from '../../sandbox/session-sandbox.js';\nimport { peekSessionSandbox } from '../../sandbox/session-sandbox.js';\nimport { sanitizeSegment } from '../../sandbox/workdir.js';\nimport { normalizeSessionTitle } from '../../session/session-title.js';\nimport type { StateSigner } from '../../state-signing.js';\nimport type { AuditEmitter } from '../../storage/domains/audit/domain.js';\nimport type { MemorySettingsStorage } from '../../storage/domains/memory-settings/base.js';\nimport type { FactoryProjectsStorage } from '../../storage/domains/projects/base.js';\nimport type {\n ProjectRepository,\n ProjectSourceControlConnection,\n SourceControlInstallation,\n SourceControlRepository,\n} from '../../storage/domains/source-control/base.js';\nimport { listRepositoryCommits } from './commits.js';\nimport { getGithubFeatureDiagnostics, isGithubFeatureEnabled } from './config.js';\nimport type { GithubIntegration } from './integration.js';\nimport { clearGithubPat, getGithubPat, getGithubPatStatus, setGithubPat } from './pat.js';\nimport type { GithubPatKind } from './pat.js';\n\nimport { reclaimDeletedSessionSandbox } from './sandbox-release.js';\nimport {\n commitAll,\n isValidGitRef as isValidGitRefSandbox,\n MaterializeError,\n pushBranch,\n SetupCommandError,\n} from './sandbox.js';\nimport type { GitIdentity } from './sandbox.js';\n\nconst sessionOperationLocks = new Map<string, Promise<unknown>>();\nconst USER_SESSION_BRANCH_PREFIX = 'user/session-';\n// lowercase only (crypto.randomUUID output), so casing cannot fork one logical ID into two sessions\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;\n/**\n * Serialize same-session mutations within one Factory process. Factory sessions\n * normally issue these operations sequentially, so this lock is probably not\n * necessary; keep the cheap local guard until that invariant is enforced by\n * the request protocol. It intentionally does not consume a database connection.\n */\nfunction withSessionOperationLock<T>(sessionId: string, fn: () => Promise<T>): Promise<T> {\n const previous = sessionOperationLocks.get(sessionId) ?? Promise.resolve();\n const next = previous.then(fn, fn);\n const tail = next.then(\n () => undefined,\n () => undefined,\n );\n sessionOperationLocks.set(sessionId, tail);\n void tail.then(() => {\n if (sessionOperationLocks.get(sessionId) === tail) sessionOperationLocks.delete(sessionId);\n });\n return next;\n}\nimport { listPullRequestSubscriptionsForThread, subscribeToPullRequest } from './subscriptions.js';\nimport { handleGithubWebhook } from './webhook.js';\nimport type { ParsedGithubWebhook } from './webhook.js';\n\n/**\n * Loose Hono context accepted by the shared GitHub route helpers. The\n * `registerApiRoute` handlers receive a path-parameterized context whose\n * `HonoRequest` literal-path generics are invariant and don't flow into a\n * shared helper signature. The helpers only ever touch cookies/query/tenant, so\n * we erase the path to a plain `Context` at the call boundary via `loose()`.\n */\ntype RouteContext = Context;\n\n/** Erase a route handler's path-parameterized context to a plain `Context`. */\nfunction loose(c: unknown): RouteContext {\n return c as RouteContext;\n}\n\nexport interface MountGithubRoutesOptions {\n /** Host auth seam — resolves the signed-in user/tenant for each request. */\n auth: RouteAuth;\n /** Optional user directory used to resolve session-owner display profiles. */\n users?: SessionOwnerUserProvider;\n /**\n * The host's session-sandbox callback. Routes only read whether it is\n * configured: without one, `/web/github/status` reports\n * `sandboxEnabled: false` and sandbox-backed routes respond 503. Sandboxes\n * themselves are constructed per session and started lazily elsewhere.\n */\n sandbox?: MastraFactorySandboxConfig;\n /** Factory storage backend used for the `appDbConfigured` diagnostic. */\n storage?: FactoryStorage;\n /**\n * The GitHub App integration the handlers operate on (Octokit access, token\n * minting, OAuth URLs). Normally supplied by `GithubIntegration.routes()`;\n * when absent, only the disabled `status` route is served.\n */\n github?: GithubIntegration;\n /**\n * Shared OAuth/install `state` signer (created once per boot by the\n * factory). Required for the OAuth/install flow; when absent, only the\n * disabled `status` route is served.\n */\n stateSigner?: StateSigner;\n /**\n * Absolute base URL of the web server (e.g. `http://localhost:4111`), used to\n * build the OAuth/install redirect URI when one isn't explicitly configured.\n */\n baseUrl?: string;\n /** Explicit OAuth callback URI; defaults to `<baseUrl>/auth/github/callback`. */\n redirectUri?: string;\n /** Controller used to route verified webhook notifications to exact subscribed sessions. */\n controller?: MountedMastraCode['controller'];\n /** Owner-scoped observational-memory settings — the source of the model that names a thread. */\n memorySettings: Pick<MemorySettingsStorage, 'get'>;\n /** Best-effort audit emission supplied by the factory-owned audit domain. */\n emitAudit?: AuditEmitter['emit'];\n /** Factory projects domain — resolves a project's default triage model. */\n projects?: FactoryProjectsStorage;\n sessionRetirement?: import('../../sandbox/session-retirement.js').SessionRetirementCoordinator;\n /** Work-items domain — session deletion strips the refs work items hold on it. */\n workItems?: Pick<import('../../storage/domains/work-items/base.js').WorkItemsStorage, 'clearSessionReferences'>;\n /** Authoritative Factory rule ingress for normalized, signature-verified GitHub deliveries. */\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n}\n\nfunction pullRequestNumberFromUrl(value: string, expectedRepo: string): number | undefined {\n try {\n const url = new URL(value);\n const match = url.pathname.match(/^\\/([^/]+\\/[^/]+)\\/pull\\/(\\d+)\\/?$/);\n if (\n url.protocol !== 'https:' ||\n url.hostname !== 'github.com' ||\n match?.[1]?.toLowerCase() !== expectedRepo.toLowerCase()\n ) {\n return undefined;\n }\n const number = Number(match[2]);\n return Number.isInteger(number) && number > 0 ? number : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Validate a git branch/ref name against a strict whitelist. The value is later\n * interpolated into a shell `git clone --branch` command, so it must never\n * contain shell metacharacters. We accept only git-ref-safe characters and\n * reject anything else rather than relying on shell quoting alone.\n */\nfunction isValidGitRef(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 && value.length <= 255 && /^[A-Za-z0-9_./-]+$/.test(value);\n}\n\nfunction isJsonObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Resolve the org-scoped tenant for a GitHub request. GitHub project features\n * are org-owned, so they require both a signed-in user and a WorkOS\n * organization. Returns the `(orgId, userId)` tenant (with `orgId` narrowed to a\n * non-null string) or a ready-to-return error response: 401 when unauthenticated,\n * 403 when the user has no organization (personal account).\n *\n * Resolves the session from the request cookie itself (via `auth.ensureUser`)\n * instead of relying on the auth gate's context stash: on platform deploys\n * custom `apiRoutes` run on an isolated sub-app context where the gate's\n * `c.set(...)` is invisible. When the gate stash IS visible (local Hono\n * server), `auth.ensureUser` returns the cached user and this is a no-op.\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' }, 401) };\n if (!tenant.orgId) {\n return {\n response: c.json(\n {\n error: 'organization_required',\n message: 'GitHub projects require a WorkOS organization. Personal accounts cannot connect repositories.',\n },\n 403,\n ),\n };\n }\n return { tenant: { orgId: tenant.orgId, userId: tenant.userId } };\n}\n\n/**\n * Parse a 1-based `page` query param. Missing means page 1; anything that is\n * not a small positive integer is rejected (`null`).\n */\nfunction parseListPage(raw: string | undefined): number | null {\n if (raw === undefined) return 1;\n if (!/^\\d{1,5}$/.test(raw)) return null;\n const page = Number(raw);\n return page >= 1 ? page : null;\n}\n\nfunction parseResourceNumber(raw: string | undefined): number | null {\n if (raw === undefined || !/^\\d{1,10}$/.test(raw)) return null;\n const parsed = Number(raw);\n return parsed > 0 ? parsed : null;\n}\n\nconst VALID_ISSUE_LABEL_FILTERS = new Set<string>([AUTO_TRIAGED_LABEL, NEEDS_APPROVAL_LABEL]);\n\nfunction parseIssueLabelFilter(raw: string | undefined): string | undefined | null {\n if (raw === undefined || raw === '') return undefined;\n if (VALID_ISSUE_LABEL_FILTERS.has(raw)) return raw;\n return null;\n}\n\ninterface ResolvedProjectRepository extends ProjectRepository {\n connection: ProjectSourceControlConnection;\n installation: SourceControlInstallation;\n repository: SourceControlRepository;\n factoryProjectId: string;\n defaultBranch: string;\n}\n\nasync function resolveProjectRepository(args: {\n github: GithubIntegration;\n orgId: string;\n projectRepositoryId: string;\n}): Promise<ResolvedProjectRepository | null> {\n const projectRepository = await args.github.sourceControlStorage.projectRepositories.get({\n orgId: args.orgId,\n id: args.projectRepositoryId,\n });\n if (!projectRepository) return null;\n const connection = await args.github.sourceControlStorage.connections.get({\n orgId: args.orgId,\n id: projectRepository.connectionId,\n });\n if (!connection) return null;\n const repository = await args.github.sourceControlStorage.repositories.get({\n orgId: args.orgId,\n id: projectRepository.repositoryId,\n });\n if (!repository) return null;\n const installation = await args.github.sourceControlStorage.installations.get({\n orgId: args.orgId,\n id: connection.installationId,\n });\n if (!installation) return null;\n return {\n ...projectRepository,\n connection,\n installation,\n repository,\n factoryProjectId: connection.factoryProjectId,\n defaultBranch: projectRepository.branch ?? repository.defaultBranch,\n };\n}\n\nfunction polledIssueEvent(\n project: ResolvedProjectRepository,\n issue: {\n number: number;\n title: string;\n url: string;\n author: string | null;\n assignee: string | null;\n assignees?: string[];\n labels: string[];\n createdAt: string;\n },\n): ParsedGithubWebhook {\n const repositoryId = Number(project.repository.externalId);\n const assigneeLogins = issue.assignees ?? (issue.assignee ? [issue.assignee] : []);\n return {\n event: 'issues',\n deliveryId: `poll:${repositoryId}:issue:${issue.number}:${issue.createdAt}`,\n payload: {\n action: 'opened',\n installation: { id: Number(project.installation.externalId) },\n repository: { id: repositoryId, full_name: project.repository.slug },\n sender: { login: issue.author ?? '__unknown__' },\n issue: {\n number: issue.number,\n title: issue.title,\n html_url: issue.url,\n created_at: issue.createdAt,\n assignees: assigneeLogins.map(login => ({ login })),\n labels: issue.labels.map(name => ({ name })),\n },\n },\n };\n}\n\nfunction polledPullRequestEvent(\n project: ResolvedProjectRepository,\n pullRequest: {\n number: number;\n title: string;\n url: string;\n author: string | null;\n assignees: string[];\n requestedReviewers: string[];\n headBranch: string;\n baseBranch: string;\n createdAt: string;\n },\n): ParsedGithubWebhook {\n const repositoryId = Number(project.repository.externalId);\n return {\n event: 'pull_request',\n deliveryId: `poll:${repositoryId}:pull-request:${pullRequest.number}:${pullRequest.createdAt}`,\n payload: {\n action: 'opened',\n installation: { id: Number(project.installation.externalId) },\n repository: { id: repositoryId, full_name: project.repository.slug },\n sender: { login: pullRequest.author ?? '__unknown__' },\n pull_request: {\n number: pullRequest.number,\n title: pullRequest.title,\n html_url: pullRequest.url,\n created_at: pullRequest.createdAt,\n state: 'open',\n merged: false,\n assignees: pullRequest.assignees.map(login => ({ login })),\n requested_reviewers: pullRequest.requestedReviewers.map(login => ({ login })),\n head: { ref: pullRequest.headBranch },\n base: { ref: pullRequest.baseBranch },\n },\n },\n };\n}\n\nasync function ingestPolledEvents(\n events: ParsedGithubWebhook[],\n ingestFactoryEvent: MountGithubRoutesOptions['ingestFactoryEvent'],\n): Promise<void> {\n if (!ingestFactoryEvent) return;\n const results = await Promise.allSettled(events.map(event => ingestFactoryEvent(event)));\n const rejected = results.find((result): result is PromiseRejectedResult => result.status === 'rejected');\n if (rejected) throw rejected.reason;\n}\n\n/**\n * Build the GitHub routes as Mastra `apiRoutes`. When the feature is disabled,\n * returns only the `status` route so the SPA can detect the disabled state.\n */\nexport function buildGithubRoutes(options: MountGithubRoutesOptions): ApiRoute[] {\n const routes: ApiRoute[] = [];\n const {\n auth,\n sandbox,\n users,\n storage,\n github,\n stateSigner,\n controller,\n memorySettings,\n emitAudit,\n sessionRetirement,\n workItems,\n } = options;\n const diagnostics = () =>\n getGithubFeatureDiagnostics({ github, auth, appDbConfigured: storage !== undefined, stateSigner, sandbox });\n\n // The status route is always registered so the SPA can detect the disabled state.\n routes.push(\n registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n if (!isGithubFeatureEnabled({ github, auth }) || !github || !stateSigner) {\n return c.json({\n enabled: false,\n connected: false,\n installations: [],\n reason: 'missing_config',\n diagnostics: diagnostics(),\n });\n }\n // Resolve the session from the request cookie: on platform deploys custom\n // apiRoutes run on an isolated context where the gate's stash is invisible.\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\n // Org-scoped: personal (no-org) users have GitHub projects disabled. Report\n // enabled (so the SPA can show the org-required hint) but never connected.\n if (!tenant.orgId) {\n return c.json({\n enabled: true,\n sandboxEnabled: !!sandbox,\n organizationRequired: true,\n connected: false,\n installations: [],\n reason: 'organization_required',\n diagnostics: diagnostics(),\n });\n }\n\n const rows = options.github\n ? await options.github.sourceControlStorage.installations.list({ orgId: tenant.orgId })\n : [];\n\n const connected = rows.length > 0;\n return c.json({\n enabled: true,\n sandboxEnabled: !!sandbox,\n connected,\n installations: rows.map(r => ({\n installationId: Number(r.externalId),\n accountLogin: r.accountName,\n accountType: r.accountType,\n })),\n reason: connected ? 'ready' : 'not_connected',\n diagnostics: diagnostics(),\n });\n },\n }),\n );\n\n // Without an integration instance + state signer there is nothing the\n // remaining handlers can do — serve only the disabled `status` route\n // (mirrors the feature gate).\n if (!isGithubFeatureEnabled({ github, auth }) || !github || !stateSigner) {\n return routes;\n }\n const signState = (orgId: string, userId: string): string => stateSigner.sign(orgId, userId);\n const verifyState = (state: string | undefined) => stateSigner.verify(state);\n\n routes.push(\n registerApiRoute('/web/github/subscriptions', {\n method: 'GET',\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 const resourceId = c.req.query('resourceId');\n const threadId = c.req.query('threadId');\n const sessionScope = c.req.query('scope');\n if (!resourceId || !threadId) return c.json({ error: 'resourceId and threadId are required' }, 400);\n\n const subscriptions = await listPullRequestSubscriptionsForThread(\n {\n orgId: tenant.orgId,\n resourceId,\n threadId,\n sessionScope,\n },\n github.integrationStorage,\n );\n return c.json({\n subscriptions: subscriptions.map(subscription => ({\n id: subscription.id,\n repoFullName: subscription.data.repositorySlug,\n pullRequestNumber: Number(subscription.data.changeRequestId),\n status: subscription.status,\n url: `https://github.com/${subscription.data.repositorySlug}/pull/${subscription.data.changeRequestId}`,\n })),\n });\n },\n }),\n registerApiRoute('/web/github/webhook', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const result = await handleGithubWebhook(loose(c), {\n github,\n ingestFactoryEvent: options.ingestFactoryEvent,\n ...(options.controller\n ? {\n controller: options.controller,\n onTargetError: (subscription, error) => {\n console.warn(\n `[GitHub 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\n const redirectUri = options.redirectUri ?? `${(options.baseUrl ?? '').replace(/\\/$/, '')}/auth/github/callback`;\n\n // ── Connect: bounce through the OAuth identify flow ─────────────────────\n // Identify-first (rather than install-first) so an app that is *already*\n // installed on the org re-syncs into our DB: GitHub's install page dead-ends\n // on the installation settings screen for existing installs and never\n // redirects back to us. The callback persists whatever installations the\n // verified user token can see, and only redirects to the install URL when\n // there are none.\n //\n // `?manage=1` skips the identify bounce and sends the user straight to\n // GitHub's installation page — used by \"Manage GitHub connection\" to\n // add/remove accounts and repo access. For an already-authorized user the\n // identify flow completes instantly and invisibly, so without this the\n // manage button would appear to do nothing. GitHub's post-install \"Save\"\n // redirect lands back on the callback, which re-syncs installations.\n routes.push(\n registerApiRoute('/auth/github/connect', {\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 state = signState(resolved.tenant.orgId, resolved.tenant.userId);\n if (c.req.query('manage')) return c.redirect(github.buildInstallUrl(state));\n return c.redirect(github.buildOAuthIdentifyUrl(state, redirectUri));\n },\n }),\n );\n\n // ── Callback: confirm identity, persist the installation against the org ──\n routes.push(\n registerApiRoute('/auth/github/callback', {\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 { orgId, userId } = resolved.tenant;\n\n const state = c.req.query('state');\n if (!state) {\n // GitHub's \"Save\"/update redirect from the installation settings page\n // arrives with `installation_id` + `setup_action` but no state. We\n // never trust the raw installation_id; start a fresh identify bounce\n // bound to the current session so the update re-syncs installations.\n return c.redirect(github.buildOAuthIdentifyUrl(signState(orgId, userId), redirectUri));\n }\n const stateTenant = verifyState(state);\n if (!stateTenant || stateTenant.userId !== userId || stateTenant.orgId !== orgId) {\n // CSRF / cross-user/org linking protection: the signed state must belong\n // to the same logged-in user *and* their current org.\n console.warn(\n '[GitHub] Install callback rejected: state/tenant mismatch.',\n JSON.stringify({\n stateValid: Boolean(stateTenant),\n stateOrgId: stateTenant?.orgId,\n stateUserId: stateTenant?.userId,\n sessionOrgId: orgId,\n sessionUserId: userId,\n }),\n );\n return c.redirect('/?github=error');\n }\n\n const code = c.req.query('code');\n // We only ever persist installations that GitHub confirms belong to *this*\n // user via the OAuth code path. The raw `installation_id` from the install\n // redirect is not trusted on its own — anyone with a valid state could pass\n // an arbitrary id — so when no code is present we bounce through the OAuth\n // identify flow to obtain a verified user token first.\n if (!code) {\n return c.redirect(github.buildOAuthIdentifyUrl(signState(orgId, userId), redirectUri));\n }\n\n try {\n const userToken = await github.exchangeOAuthCode(code, redirectUri);\n const installations = await github.listUserInstallations(userToken);\n if (installations.length === 0) {\n // Verified user has no installations yet — send them to the actual\n // install page. After installing, GitHub redirects back here with\n // the same state (and no code), which bounces through identify\n // again and lands in the persist path below.\n return c.redirect(github.buildInstallUrl(signState(orgId, userId)));\n }\n for (const inst of installations) {\n // The installation is org-owned; `userId` records who connected it.\n await github.sourceControlStorage.installations.upsert({\n orgId,\n connectedByUserId: userId,\n externalId: inst.installationId.toString(),\n accountName: inst.accountLogin,\n accountType: inst.accountType,\n });\n }\n } catch (error) {\n console.warn(\n `[GitHub] Install callback failed to persist installations for org ${orgId} / user ${userId}.`,\n error,\n );\n return c.redirect('/?github=error');\n }\n\n return c.redirect('/?github=connected');\n },\n }),\n );\n\n // ── List repos across the org's installations ───────────────────────────\n routes.push(\n registerApiRoute('/web/github/repos', {\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\n const orgId = resolved.tenant.orgId;\n const installs = await github.sourceControlStorage.installations.list({ orgId });\n\n const query = (c.req.query('q') ?? '').toLowerCase();\n // List every installation's repositories in parallel — installations\n // are independent upstream calls, and serial listing multiplied\n // worst-case latency by installation count.\n const listed = await Promise.all(\n installs.map(async inst => {\n try {\n return { inst, list: await github.listInstallationRepos(Number(inst.externalId)) };\n } catch (err) {\n // GitHub 404s when the installation no longer exists for this app\n // (app uninstalled/reinstalled, or the row was recorded under\n // different app credentials). Prune the stale row so `/status`\n // reflects reality and the UI prompts a reconnect, then keep\n // listing the remaining installations.\n if ((err as { status?: number }).status !== 404) throw err;\n console.error(`[Mastra Factory] pruning stale GitHub installation ${inst.externalId} (404 from GitHub)`);\n await github.sourceControlStorage.installations.delete({ orgId, id: inst.id });\n return { inst, list: [] };\n }\n }),\n );\n\n // Filter + dedupe by repo id in installation order — same result\n // ordering as the previous serial loop.\n const matches = [];\n const seenRepositoryIds = new Set<number>();\n for (const { inst, list } of listed) {\n for (const repo of list) {\n if (query && !repo.fullName.toLowerCase().includes(query)) continue;\n if (seenRepositoryIds.has(repo.id)) continue;\n seenRepositoryIds.add(repo.id);\n matches.push({ inst, repo });\n }\n }\n\n const repos = matches.map(({ inst, repo }) => ({\n ...repo,\n installationStorageId: inst.id,\n sandboxProvider: sandbox ? 'custom' : 'none',\n // Display only — the runtime workdir is resolved from the\n // live sandbox at open time. Repositories are persisted only after\n // selection, so `~/<repo>` is the honest listing-time guess.\n sandboxWorkdir: `~/${sanitizeSegment(repo.fullName.split('/', 2)[1] || 'repo')}`,\n }));\n return c.json({ repos });\n },\n }),\n );\n\n // ── List a project's open GitHub issues ──────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/issues', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const page = parseListPage(c.req.query('page'));\n if (page === null) return c.json({ error: 'invalid_page' }, 400);\n const label = parseIssueLabelFilter(c.req.query('label'));\n if (label === null) return c.json({ error: 'invalid_label' }, 400);\n try {\n const { issues, nextCursor } = await github.intake.listIssues({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceIds: [loaded.project.repository.slug],\n labels: label ? [label] : undefined,\n cursor: String(page),\n });\n const responseIssues = issues.map(issue => ({\n number: Number(issue.id),\n title: issue.title,\n url: issue.url,\n author: issue.author,\n assignee: issue.assignee,\n assignees: issue.assignees,\n labels: issue.labels,\n comments: issue.commentCount ?? 0,\n createdAt: issue.createdAt,\n updatedAt: issue.updatedAt,\n }));\n await ingestPolledEvents(\n responseIssues.map(issue => polledIssueEvent(loaded.project, issue)),\n options.ingestFactoryEvent,\n );\n return c.json({\n issues: responseIssues,\n nextPage: nextCursor === null ? null : Number(nextCursor),\n });\n } catch (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n routes.push(\n registerApiRoute('/web/github/projects/:id/issues/:number', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const number = parseResourceNumber(c.req.param('number'));\n if (number === null) return c.json({ error: 'invalid_number' }, 400);\n try {\n const detail = await github.intake.getIssue({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceId: loaded.project.repository.slug,\n issueId: String(number),\n });\n if (detail === null) return c.json({ error: 'issue_not_found' }, 404);\n return c.json({\n number: Number(detail.id),\n title: detail.title,\n url: detail.url,\n author: detail.author,\n assignee: detail.assignee,\n labels: detail.labels,\n comments: detail.commentCount ?? 0,\n createdAt: detail.createdAt,\n updatedAt: detail.updatedAt,\n description: detail.description,\n });\n } catch (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n // ── List a project's open (non-draft) pull requests ─────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/prs', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const page = parseListPage(c.req.query('page'));\n if (page === null) return c.json({ error: 'invalid_page' }, 400);\n try {\n const { pullRequests, nextCursor } = await github.versionControl.listPullRequests({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceId: loaded.project.repository.slug,\n includeDrafts: false,\n cursor: String(page),\n });\n const responsePullRequests = pullRequests.map(pr => ({\n number: Number(pr.id),\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 }));\n await ingestPolledEvents(\n responsePullRequests.map(pullRequest => polledPullRequestEvent(loaded.project, pullRequest)),\n options.ingestFactoryEvent,\n );\n return c.json({\n pullRequests: responsePullRequests,\n nextPage: nextCursor === null ? null : Number(nextCursor),\n });\n } catch (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n routes.push(\n registerApiRoute('/web/github/projects/:id/prs/:number', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const number = parseResourceNumber(c.req.param('number'));\n if (number === null) return c.json({ error: 'invalid_number' }, 400);\n try {\n const pr = await github.versionControl.getPullRequest({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceId: loaded.project.repository.slug,\n pullRequestId: String(number),\n });\n if (pr === null) return c.json({ error: 'pull_request_not_found' }, 404);\n return c.json({\n number: Number(pr.id),\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 (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n // ── Read per-project settings ────────────────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/settings', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n return c.json({\n setupCommand: loaded.project.setupCommand,\n teardownCommand: loaded.project.teardownCommand,\n });\n },\n }),\n );\n\n // ── Update per-project settings ──────────────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/settings', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n\n let body: { setupCommand?: unknown; teardownCommand?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n\n const commands = ['setupCommand', 'teardownCommand'] as const;\n for (const command of commands) {\n const value = body[command];\n if (value === undefined) continue;\n if (value !== null && typeof value !== 'string') {\n return c.json({ error: `Invalid ${command}` }, 400);\n }\n if (typeof value === 'string' && value.length > 2000) {\n return c.json({ error: `${command} too long (max 2000 characters)` }, 400);\n }\n // Reject control characters (except newline/tab). Commands are shell\n // scripts by design, but escape sequences and NULs can spoof logs or\n // confuse the sandbox shell.\n if (typeof value === 'string' && /[\\0-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/.test(value)) {\n return c.json({ error: `${command} contains control characters` }, 400);\n }\n }\n\n const normalizeCommand = (value: unknown): string | null | undefined => {\n if (value === undefined) return undefined;\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;\n };\n const setupCommand = normalizeCommand(body.setupCommand);\n const teardownCommand = normalizeCommand(body.teardownCommand);\n\n await github.sourceControlStorage.projectRepositories.update({\n orgId: loaded.project.installation.orgId,\n id: loaded.project.id,\n input: {\n ...(setupCommand !== undefined ? { setupCommand } : {}),\n ...(teardownCommand !== undefined ? { teardownCommand } : {}),\n },\n });\n return c.json({\n setupCommand: setupCommand === undefined ? loaded.project.setupCommand : setupCommand,\n teardownCommand: teardownCommand === undefined ? loaded.project.teardownCommand : teardownCommand,\n });\n },\n }),\n );\n\n // ── Org GitHub PATs ──────────────────────────────────────────────────────\n // Installation tokens are the wrong credential for the `gh` CLI (integration\n // -restricted endpoints 403 regardless of permissions), so orgs paste\n // classic PATs the sandboxes use instead: a `default` worker token, and an\n // optional `reviewer` token that review-board sessions use so PR reviews\n // come from a different account. Tokens are never sent back to the browser —\n // only whether each is configured.\n const parsePatKind = (value: unknown): GithubPatKind | null => {\n if (value === undefined || value === null || value === 'default') return 'default';\n if (value === 'reviewer') return 'reviewer';\n return null;\n };\n routes.push(\n registerApiRoute('/web/github/pat', {\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 return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n registerApiRoute('/web/github/pat', {\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\n let body: { token?: unknown; kind?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const kind = parsePatKind(body.kind);\n if (!kind) return c.json({ error: \"kind must be 'default' or 'reviewer'\" }, 400);\n const token = typeof body.token === 'string' ? body.token.trim() : '';\n if (!token) return c.json({ error: 'A token is required' }, 400);\n if (token.length > 500) return c.json({ error: 'Token too long (max 500 characters)' }, 400);\n if (/\\s/.test(token)) return c.json({ error: 'Token must not contain whitespace' }, 400);\n\n await setGithubPat(github.integrationStorage, resolved.tenant.orgId, token, kind);\n return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n registerApiRoute('/web/github/pat', {\n method: 'DELETE',\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 kind = parsePatKind(c.req.query('kind'));\n if (!kind) return c.json({ error: \"kind must be 'default' or 'reviewer'\" }, 400);\n await clearGithubPat(github.integrationStorage, resolved.tenant.orgId, kind);\n return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n );\n\n // ── Sessions / commit / push / PR ────────────────────────────────────────\n routes.push(\n ...buildProjectGitRoutes({\n github,\n auth,\n sandbox,\n users,\n controller,\n memorySettings,\n emitAudit,\n sessionRetirement,\n workItems,\n }),\n );\n\n return routes;\n}\n\n/**\n * Load the org-owned project for a read-only GitHub API route. Unlike\n * `loadOwnedProject`, this never touches sandbox state — the issues/PR list\n * routes only need the repo + installation, so they work before a sandbox is\n * ever provisioned.\n */\nasync function loadOrgProject(options: {\n github: GithubIntegration;\n auth: RouteAuth;\n c: RouteContext;\n}): Promise<{ project: ResolvedProjectRepository; orgId: string; userId: string } | { response: Response }> {\n const { github, auth, c } = options;\n const resolved = await resolveOrgTenant(c, auth);\n if ('response' in resolved) return { response: resolved.response };\n const { orgId, userId } = resolved.tenant;\n\n const projectRepositoryId = c.req.param('id');\n if (!projectRepositoryId) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n const project = await resolveProjectRepository({ github, orgId, projectRepositoryId });\n if (!project) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n return { project, orgId, userId };\n}\n\n/** Derive a commit/author identity from the authenticated host user. */\nfunction identityFromUser(user: unknown): GitIdentity {\n const u = user as { name?: string; email?: string } | null | undefined;\n return { name: u?.name ?? null, email: u?.email ?? null };\n}\n\n/** Map a sandbox/setup-command error to an actionable HTTP response. */\nfunction gitErrorResponse(c: Context, err: unknown) {\n if (err instanceof SetupCommandError) {\n return c.json({ error: err.code, message: err.message }, 502);\n }\n if (err instanceof MaterializeError) {\n return c.json({ error: err.code, message: err.message }, 502);\n }\n return c.json({ error: 'git_failed', message: err instanceof Error ? err.message : String(err) }, 500);\n}\n\n/**\n * Load the org-owned project for a git route. Centralizes the auth +\n * org/ownership checks every git route shares: the project is scoped by\n * `(id, orgId)`. Returns the tenant and project, or a ready-to-return error\n * response.\n */\nasync function loadOwnedProject(options: {\n github: GithubIntegration;\n auth: RouteAuth;\n sandbox?: MastraFactorySandboxConfig;\n c: RouteContext;\n}): Promise<{ orgId: string; userId: string; project: ResolvedProjectRepository } | { response: Response }> {\n const { github, auth, sandbox, c } = options;\n const resolved = await resolveOrgTenant(c, auth);\n if ('response' in resolved) return { response: resolved.response };\n const { orgId, userId } = resolved.tenant;\n\n if (!sandbox) {\n return {\n response: c.json({ error: 'sandbox_not_configured', message: 'No sandbox provider is configured.' }, 503),\n };\n }\n\n const projectRepositoryId = c.req.param('id');\n if (!projectRepositoryId) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n const project = await resolveProjectRepository({ github, orgId, projectRepositoryId });\n if (!project) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n return { orgId, userId, project };\n}\n\n/**\n * One naming per session at a time: a second caller joins the run already in\n * flight instead of paying for another model call and racing its rename.\n */\nfunction createSessionNaming() {\n const inFlight = new Map<string, Promise<string | null>>();\n return (sessionId: string, run: () => Promise<string | null>) => {\n const pending = inFlight.get(sessionId);\n if (pending) return pending;\n const started = run().finally(() => inFlight.delete(sessionId));\n inFlight.set(sessionId, started);\n return started;\n };\n}\n\n/**\n * Name a thread with a stored model id. Resolution has to go through\n * mastracode's gateway: a bare id handed to core's model router looks for a\n * process env key instead of the caller's stored provider credentials.\n */\nfunction titleModel(modelId: string) {\n return ({ requestContext }: { requestContext: RequestContext }) =>\n resolveModel(modelId, { remapForCodexOAuth: true, requestContext });\n}\n\ninterface SessionOwnerProfile {\n id: string;\n name: string;\n avatarUrl?: string;\n}\n\ntype SessionOwnerUserProvider = Pick<IUserProvider, 'getUser'> & Partial<Pick<IUserProvider, 'getUsers'>>;\n\n/** A screenful of history; GitHub caps its own page at 100. */\nconst DEFAULT_COMMIT_PAGE = 20;\nconst MAX_COMMIT_PAGE = 100;\n\nconst MAX_SESSION_OWNER_PROFILES = 100;\nconst MAX_SESSION_OWNER_PROFILE_CACHE_ENTRIES = 500;\nconst SESSION_OWNER_PROFILE_TTL_MS = 5 * 60_000;\n\nfunction createSessionOwnerProfileResolver(users: SessionOwnerUserProvider | undefined) {\n const cache = new Map<string, { profile?: SessionOwnerProfile; expiresAt: number }>();\n const cacheProfile = (userId: string, profile: SessionOwnerProfile | undefined, expiresAt: number) => {\n cache.delete(userId);\n cache.set(userId, { profile, expiresAt });\n if (cache.size > MAX_SESSION_OWNER_PROFILE_CACHE_ENTRIES) {\n const oldestUserId = cache.keys().next().value;\n if (oldestUserId !== undefined) cache.delete(oldestUserId);\n }\n };\n\n return async (userIds: string[]): Promise<Map<string, SessionOwnerProfile>> => {\n if (!users) return new Map();\n\n const requestedUserIds = [...new Set(userIds)].slice(0, MAX_SESSION_OWNER_PROFILES);\n const profiles = new Map<string, SessionOwnerProfile>();\n const unresolvedUserIds: string[] = [];\n const now = Date.now();\n\n for (const userId of requestedUserIds) {\n const cached = cache.get(userId);\n if (!cached || cached.expiresAt <= now) {\n cache.delete(userId);\n unresolvedUserIds.push(userId);\n } else if (cached.profile) {\n profiles.set(userId, cached.profile);\n }\n }\n\n if (unresolvedUserIds.length === 0) return profiles;\n\n let resolvedUsers: Array<Awaited<ReturnType<SessionOwnerUserProvider['getUser']>>>;\n if (users.getUsers) {\n try {\n resolvedUsers = await users.getUsers(unresolvedUserIds);\n } catch (error) {\n console.warn('[GitHub Sessions] Bulk session owner profile lookup failed; falling back to individual lookups', {\n error: error instanceof Error ? error.message : String(error),\n });\n resolvedUsers = (await Promise.allSettled(unresolvedUserIds.map(userId => users.getUser(userId))))\n .filter(result => result.status === 'fulfilled')\n .map(result => result.value);\n }\n } else {\n resolvedUsers = (await Promise.allSettled(unresolvedUserIds.map(userId => users.getUser(userId))))\n .filter(result => result.status === 'fulfilled')\n .map(result => result.value);\n }\n\n for (const user of resolvedUsers) {\n if (!user) continue;\n const name = user.name?.trim() || user.email?.trim();\n if (!name) continue;\n profiles.set(user.id, {\n id: user.id,\n name,\n ...(user.avatarUrl ? { avatarUrl: user.avatarUrl } : {}),\n });\n }\n\n const expiresAt = now + SESSION_OWNER_PROFILE_TTL_MS;\n for (const userId of unresolvedUserIds) {\n cacheProfile(userId, profiles.get(userId), expiresAt);\n }\n return profiles;\n };\n}\n\nfunction buildProjectGitRoutes({\n github,\n auth,\n sandbox,\n users,\n controller,\n memorySettings,\n emitAudit,\n sessionRetirement,\n workItems,\n}: {\n github: GithubIntegration;\n auth: RouteAuth;\n sandbox?: MastraFactorySandboxConfig;\n users?: SessionOwnerUserProvider;\n controller?: MountedMastraCode['controller'];\n memorySettings: MountGithubRoutesOptions['memorySettings'];\n emitAudit?: AuditEmitter['emit'];\n sessionRetirement?: MountGithubRoutesOptions['sessionRetirement'];\n workItems?: MountGithubRoutesOptions['workItems'];\n}): ApiRoute[] {\n const nameSession = createSessionNaming();\n const resolveSessionOwnerProfiles = createSessionOwnerProfileResolver(users);\n return [\n // ── Create / list Factory sessions ──────────────────────────────────────\n registerApiRoute('/web/github/projects/:id/sessions', {\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 { orgId, userId } = resolved.tenant;\n const projectRepositoryId = c.req.param('id');\n const project = projectRepositoryId\n ? await resolveProjectRepository({ github, orgId, projectRepositoryId })\n : null;\n if (!project) return c.json({ error: 'Project repository not found' }, 404);\n const sessions = await github.sourceControlStorage.sessions.list({\n projectRepositoryId: project.id,\n viewerUserId: userId,\n });\n const owners = await resolveSessionOwnerProfiles(sessions.map(session => session.userId));\n return c.json({\n sessions: sessions.map(session => {\n const owner = owners.get(session.userId);\n return { ...session, ...(owner ? { owner } : {}) };\n }),\n });\n },\n }),\n registerApiRoute('/web/github/projects/:id/sessions', {\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 { orgId, userId } = resolved.tenant;\n const projectRepositoryId = c.req.param('id');\n const project = projectRepositoryId\n ? await resolveProjectRepository({ github, orgId, projectRepositoryId })\n : null;\n if (!project) return c.json({ error: 'Project repository not found' }, 404);\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isJsonObject(body)) return c.json({ error: 'Invalid JSON body' }, 400);\n const requestedBaseBranch = body.baseBranch;\n if (requestedBaseBranch !== undefined && typeof requestedBaseBranch !== 'string') {\n return c.json({ error: 'Invalid baseBranch' }, 400);\n }\n const baseBranch = requestedBaseBranch ?? project.defaultBranch;\n if (!isValidGitRefSandbox(baseBranch)) return c.json({ error: 'Invalid baseBranch' }, 400);\n\n const requestedSessionId = body.sessionId;\n if (\n requestedSessionId !== undefined &&\n (typeof requestedSessionId !== 'string' || !UUID_PATTERN.test(requestedSessionId))\n ) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n const sessionId = requestedSessionId ?? randomUUID();\n\n const requestedTitle = body.title;\n if (requestedTitle !== undefined && typeof requestedTitle !== 'string') {\n return c.json({ error: 'Invalid title' }, 400);\n }\n const normalizedTitle = requestedTitle === undefined ? null : normalizeSessionTitle(requestedTitle);\n\n const requestedBranch = body.branch;\n let branch: string;\n if (requestedBranch === undefined) {\n branch = `${USER_SESSION_BRANCH_PREFIX}${sessionId}`;\n } else if (typeof requestedBranch === 'string' && isValidGitRefSandbox(requestedBranch)) {\n branch = requestedBranch;\n } else {\n return c.json({ error: 'Invalid branch' }, 400);\n }\n\n if (requestedSessionId !== undefined) {\n const existing = await github.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (existing) {\n if (\n existing.projectRepositoryId !== project.id ||\n existing.orgId !== orgId ||\n existing.userId !== userId ||\n existing.branch !== branch\n ) {\n return c.json({ error: 'Session ID conflict' }, 409);\n }\n return c.json({ session: existing });\n }\n }\n\n const session = await github.sourceControlStorage.sessions\n .create({\n sessionId,\n projectRepositoryId: project.id,\n orgId,\n userId,\n branch,\n baseBranch,\n title: normalizedTitle,\n visibility: 'org',\n })\n .catch(async error => {\n if (!(error instanceof UniqueViolationError) || requestedSessionId === undefined) throw error;\n const conflict = await github.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (!conflict) throw error;\n return conflict;\n });\n if (\n requestedSessionId !== undefined &&\n (session.sessionId !== sessionId ||\n session.projectRepositoryId !== project.id ||\n session.orgId !== orgId ||\n session.userId !== userId ||\n session.branch !== branch)\n ) {\n return c.json({ error: 'Session ID conflict' }, 409);\n }\n return c.json({ session });\n },\n }),\n registerApiRoute('/web/user-sessions/:sessionId', {\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 session = await github.sourceControlStorage.sessions.getBySessionId(c.req.param('sessionId'));\n // Private sessions 404 (not 403) for non-owners so their IDs do not\n // leak existence; the body must match the genuinely-missing case.\n if (\n !session ||\n session.orgId !== resolved.tenant.orgId ||\n (session.visibility === 'private' && session.userId !== resolved.tenant.userId)\n ) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json({ session });\n },\n }),\n registerApiRoute('/web/user-sessions/:sessionId', {\n method: 'DELETE',\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 session = await github.sourceControlStorage.sessions.getBySessionId(c.req.param('sessionId'));\n if (!session || session.orgId !== resolved.tenant.orgId || session.userId !== resolved.tenant.userId) {\n return c.json({ error: 'Session not found' }, 404);\n }\n try {\n await controller?.deleteSession({ resourceId: session.sessionId });\n } catch (error) {\n console.error('[GitHub Sessions] Failed to tear down live controller session', {\n sessionId: session.sessionId,\n error,\n });\n }\n if (sessionRetirement) {\n await sessionRetirement.retireSession({\n sourceControl: github.sourceControlStorage,\n ...(workItems ? { workItems } : {}),\n orgId: session.orgId,\n sessionId: session.sessionId,\n deleteSession: true,\n });\n } else {\n await workItems?.clearSessionReferences({ orgId: session.orgId, sessionId: session.sessionId });\n await github.sourceControlStorage.sessions.delete(session.id);\n void reclaimDeletedSessionSandbox({ session }).catch((error: unknown) => {\n console.error('[GitHub Sessions] Failed to reclaim sandbox for deleted session', {\n sessionId: session.sessionId,\n sandboxId: session.sandboxId,\n error,\n });\n });\n }\n return c.json({ removed: true });\n },\n }),\n\n // ── Re-name a session's thread with the title model ────────────────────\n registerApiRoute('/web/user-sessions/:sessionId/title', {\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 sessionId = c.req.param('sessionId');\n const row = await github.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (!row || row.orgId !== resolved.tenant.orgId || row.userId !== resolved.tenant.userId) {\n return c.json({ error: 'Session not found' }, 404);\n }\n if (!controller) return c.json({ error: 'Sessions are not available on this server.' }, 503);\n\n const threads = await controller.queryThreads({ resourceId: sessionId });\n const thread = threads.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())[0];\n if (!thread) return c.json({ error: 'This session has no conversation to name yet.' }, 409);\n\n // A session that is not live carries neither the observer model that names\n // its threads nor the identity whose provider credentials pay for it.\n const stored = await memorySettings.get({ orgId: row.orgId, userId: row.userId });\n const requestContext = new RequestContext();\n requestContext.set('user', { workosId: row.userId, organizationId: row.orgId });\n\n try {\n const title = await nameSession(sessionId, async () => {\n const generated = await controller.generateThreadTitle({\n threadId: thread.id,\n resourceId: sessionId,\n requestContext,\n ...(stored?.observerModelId ? { model: titleModel(stored.observerModelId) } : {}),\n });\n const named = generated ? normalizeSessionTitle(generated) : null;\n if (named) await github.sourceControlStorage.sessions.rename({ sessionId, title: named });\n return named;\n });\n if (!title) return c.json({ error: 'The model returned an empty title. Try again.' }, 502);\n return c.json({ title });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Stage all + commit inside a Factory session workspace ──────────────\n registerApiRoute('/web/github/projects/:id/commit', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, sandbox, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { userId, project } = owned;\n\n let body: { message?: unknown; sessionId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (typeof body.message !== 'string' || body.message.trim().length === 0 || body.message.length > 5000) {\n return c.json({ error: 'Invalid message' }, 400);\n }\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n const { workdir, sandbox: sessionSandbox } = sessionWorkspace;\n\n try {\n return await withSessionOperationLock(sessionWorkspace.session.sessionId, async () => {\n const result = await commitAll(\n sessionSandbox,\n workdir,\n body.message as string,\n identityFromUser(await auth.ensureUser(loose(c))),\n );\n if (result.committed) {\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.commit',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'session', id: sessionWorkspace.session.sessionId }],\n metadata: { sessionId: sessionWorkspace.session.sessionId },\n },\n });\n }\n return c.json({ committed: result.committed });\n });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n\n // ── Recent commits on a repository branch ───────────────────────────────\n registerApiRoute('/web/github/projects/:id/commits', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const { orgId, project } = loaded;\n\n const branch = c.req.query('branch') ?? project.defaultBranch;\n if (!isValidGitRefSandbox(branch)) return c.json({ error: 'Invalid branch' }, 400);\n // GitHub takes `per_page` as an integer, so a fractional limit would go out verbatim.\n const limit = Math.min(\n Math.max(Math.floor(Number(c.req.query('limit') ?? DEFAULT_COMMIT_PAGE)) || DEFAULT_COMMIT_PAGE, 1),\n MAX_COMMIT_PAGE,\n );\n\n try {\n const commits = await listRepositoryCommits(github, { orgId, project, branch, limit });\n return c.json({ commits, branch });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n\n // ── Push a branch back to GitHub ────────────────────────────────────────\n registerApiRoute('/web/github/projects/:id/push', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, sandbox, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { orgId, userId, project } = owned;\n\n let body: { branch?: unknown; sessionId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isValidGitRefSandbox(body.branch)) {\n return c.json({ error: 'Invalid branch' }, 400);\n }\n const branch = body.branch;\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n const { workdir, sandbox: sessionSandbox } = sessionWorkspace;\n\n try {\n return await withSessionOperationLock(sessionWorkspace.session.sessionId, async () => {\n const access = await github.versionControl.getRepositoryAccess({\n orgId,\n repositoryId: project.repository.id,\n });\n if (!access.authorization) throw new Error('Repository access did not include a bearer token.');\n await pushBranch(sessionSandbox, workdir, branch, access.authorization.token, project.repository.slug);\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.push',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'branch', id: branch }],\n metadata: { branch, sessionId: sessionWorkspace.session.sessionId },\n },\n });\n return c.json({ pushed: true, branch });\n });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n\n // ── Open a pull request through the version-control capability ─────────\n registerApiRoute('/web/github/projects/:id/pr', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, sandbox, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { orgId, userId, project } = owned;\n\n let body: {\n branch?: unknown;\n base?: unknown;\n title?: unknown;\n body?: unknown;\n sessionId?: unknown;\n };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isValidGitRefSandbox(body.branch)) {\n return c.json({ error: 'Invalid branch' }, 400);\n }\n const base = body.base === undefined ? project.defaultBranch : body.base;\n if (!isValidGitRefSandbox(base)) {\n return c.json({ error: 'Invalid base' }, 400);\n }\n if (typeof body.title !== 'string' || body.title.trim().length === 0 || body.title.length > 256) {\n return c.json({ error: 'Invalid title' }, 400);\n }\n if (body.body !== undefined && (typeof body.body !== 'string' || body.body.length > 65536)) {\n return c.json({ error: 'Invalid body' }, 400);\n }\n const head = body.branch;\n const title = body.title;\n const prBody = body.body as string | undefined;\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n\n try {\n return await withSessionOperationLock(sessionWorkspace.session.sessionId, async () => {\n const result = await github.versionControl.createPullRequest({\n connection: {\n type: 'app-installation',\n installationId: Number(project.installation.externalId),\n },\n sourceId: project.repository.slug,\n baseBranch: base,\n headBranch: head,\n title,\n body: prBody,\n actingUserId: userId,\n });\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.pr_opened',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'pull_request', id: result.url, name: title }],\n metadata: { branch: head, base, url: result.url },\n },\n });\n const pullRequestNumber = pullRequestNumberFromUrl(result.url, project.repository.slug);\n if (pullRequestNumber) {\n const sessionId = sessionWorkspace.session.sessionId;\n await subscribeToPullRequest(\n {\n orgId,\n installationExternalId: project.installation.externalId,\n projectRepositoryId: project.id,\n repositoryExternalId: project.repository.externalId,\n repositorySlug: project.repository.slug,\n changeRequestId: pullRequestNumber.toString(),\n sessionId,\n ownerId: userId,\n resourceId: sessionId,\n threadId: sessionId,\n source: 'factory-pr-create',\n subscribedByUserId: userId,\n },\n github.integrationStorage,\n ).catch((error: unknown) => {\n console.warn(\n `[GitHub] Pull request ${result.url} was created but automatic subscription failed.`,\n error,\n );\n });\n }\n return c.json({ url: result.url });\n });\n } catch (err) {\n return c.json(\n { error: 'github_pr_create_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n ];\n}\n\n/** Resolve the materialized workspace owned by a Factory session. */\nasync function resolveSessionWorkspace(\n github: GithubIntegration,\n projectId: string,\n userId: string,\n sessionId: unknown,\n) {\n if (typeof sessionId !== 'string') {\n return undefined;\n }\n const session = await github.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (session?.projectRepositoryId !== projectId || session.userId !== userId) {\n return undefined;\n }\n // Session sandboxes live in the per-process memo, keyed by the session row\n // id. Passive resolution only — git write routes never provision. An\n // unresolved workdir means the sandbox never started here: nothing is\n // materialized, so there is no workspace to operate on.\n const entry = peekSessionSandbox(session.id);\n if (!entry?.workdir) return undefined;\n return {\n session,\n workdir: entry.workdir,\n sandbox: requireExec(entry.sandbox),\n };\n}\n"],"mappings":"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"}