@cat-factory/node-server 0.6.0

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 (156) hide show
  1. package/LICENSE +21 -0
  2. package/dist/config.d.ts +3 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +297 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/container.d.ts +88 -0
  7. package/dist/container.d.ts.map +1 -0
  8. package/dist/container.js +937 -0
  9. package/dist/container.js.map +1 -0
  10. package/dist/db/client.d.ts +13 -0
  11. package/dist/db/client.d.ts.map +1 -0
  12. package/dist/db/client.js +21 -0
  13. package/dist/db/client.js.map +1 -0
  14. package/dist/db/migrate.d.ts +12 -0
  15. package/dist/db/migrate.d.ts.map +1 -0
  16. package/dist/db/migrate.js +40 -0
  17. package/dist/db/migrate.js.map +1 -0
  18. package/dist/db/schema.d.ts +7858 -0
  19. package/dist/db/schema.d.ts.map +1 -0
  20. package/dist/db/schema.js +928 -0
  21. package/dist/db/schema.js.map +1 -0
  22. package/dist/environments.d.ts +11 -0
  23. package/dist/environments.d.ts.map +1 -0
  24. package/dist/environments.js +31 -0
  25. package/dist/environments.js.map +1 -0
  26. package/dist/execution/bootstrapRunner.d.ts +27 -0
  27. package/dist/execution/bootstrapRunner.d.ts.map +1 -0
  28. package/dist/execution/bootstrapRunner.js +79 -0
  29. package/dist/execution/bootstrapRunner.js.map +1 -0
  30. package/dist/execution/config.d.ts +37 -0
  31. package/dist/execution/config.d.ts.map +1 -0
  32. package/dist/execution/config.js +86 -0
  33. package/dist/execution/config.js.map +1 -0
  34. package/dist/execution/drive.d.ts +6 -0
  35. package/dist/execution/drive.d.ts.map +1 -0
  36. package/dist/execution/drive.js +13 -0
  37. package/dist/execution/drive.js.map +1 -0
  38. package/dist/execution/pgBossRunner.d.ts +82 -0
  39. package/dist/execution/pgBossRunner.d.ts.map +1 -0
  40. package/dist/execution/pgBossRunner.js +163 -0
  41. package/dist/execution/pgBossRunner.js.map +1 -0
  42. package/dist/gateways.d.ts +4 -0
  43. package/dist/gateways.d.ts.map +1 -0
  44. package/dist/gateways.js +91 -0
  45. package/dist/gateways.js.map +1 -0
  46. package/dist/index.d.ts +13 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +22 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/main.d.ts +2 -0
  51. package/dist/main.d.ts.map +1 -0
  52. package/dist/main.js +9 -0
  53. package/dist/main.js.map +1 -0
  54. package/dist/modelProvider.d.ts +6 -0
  55. package/dist/modelProvider.d.ts.map +1 -0
  56. package/dist/modelProvider.js +72 -0
  57. package/dist/modelProvider.js.map +1 -0
  58. package/dist/realtime.d.ts +62 -0
  59. package/dist/realtime.d.ts.map +1 -0
  60. package/dist/realtime.js +171 -0
  61. package/dist/realtime.js.map +1 -0
  62. package/dist/recurring.d.ts +11 -0
  63. package/dist/recurring.d.ts.map +1 -0
  64. package/dist/recurring.js +33 -0
  65. package/dist/recurring.js.map +1 -0
  66. package/dist/repositories/bootstrap.d.ts +25 -0
  67. package/dist/repositories/bootstrap.d.ts.map +1 -0
  68. package/dist/repositories/bootstrap.js +280 -0
  69. package/dist/repositories/bootstrap.js.map +1 -0
  70. package/dist/repositories/containerExecution.d.ts +33 -0
  71. package/dist/repositories/containerExecution.d.ts.map +1 -0
  72. package/dist/repositories/containerExecution.js +199 -0
  73. package/dist/repositories/containerExecution.js.map +1 -0
  74. package/dist/repositories/documents.d.ts +31 -0
  75. package/dist/repositories/documents.d.ts.map +1 -0
  76. package/dist/repositories/documents.js +176 -0
  77. package/dist/repositories/documents.js.map +1 -0
  78. package/dist/repositories/drizzle.d.ts +105 -0
  79. package/dist/repositories/drizzle.d.ts.map +1 -0
  80. package/dist/repositories/drizzle.js +1872 -0
  81. package/dist/repositories/drizzle.js.map +1 -0
  82. package/dist/repositories/environments.d.ts +23 -0
  83. package/dist/repositories/environments.d.ts.map +1 -0
  84. package/dist/repositories/environments.js +162 -0
  85. package/dist/repositories/environments.js.map +1 -0
  86. package/dist/repositories/fragments.d.ts +23 -0
  87. package/dist/repositories/fragments.d.ts.map +1 -0
  88. package/dist/repositories/fragments.js +190 -0
  89. package/dist/repositories/fragments.js.map +1 -0
  90. package/dist/repositories/github.d.ts +53 -0
  91. package/dist/repositories/github.d.ts.map +1 -0
  92. package/dist/repositories/github.js +441 -0
  93. package/dist/repositories/github.js.map +1 -0
  94. package/dist/repositories/localModelEndpoint.d.ts +12 -0
  95. package/dist/repositories/localModelEndpoint.d.ts.map +1 -0
  96. package/dist/repositories/localModelEndpoint.js +75 -0
  97. package/dist/repositories/localModelEndpoint.js.map +1 -0
  98. package/dist/repositories/notifications.d.ts +11 -0
  99. package/dist/repositories/notifications.d.ts.map +1 -0
  100. package/dist/repositories/notifications.js +88 -0
  101. package/dist/repositories/notifications.js.map +1 -0
  102. package/dist/repositories/personalSubscription.d.ts +22 -0
  103. package/dist/repositories/personalSubscription.d.ts.map +1 -0
  104. package/dist/repositories/personalSubscription.js +159 -0
  105. package/dist/repositories/personalSubscription.js.map +1 -0
  106. package/dist/repositories/providerApiKey.d.ts +18 -0
  107. package/dist/repositories/providerApiKey.d.ts.map +1 -0
  108. package/dist/repositories/providerApiKey.js +111 -0
  109. package/dist/repositories/providerApiKey.js.map +1 -0
  110. package/dist/repositories/providerSubscription.d.ts +16 -0
  111. package/dist/repositories/providerSubscription.d.ts.map +1 -0
  112. package/dist/repositories/providerSubscription.js +88 -0
  113. package/dist/repositories/providerSubscription.js.map +1 -0
  114. package/dist/repositories/slack.d.ts +23 -0
  115. package/dist/repositories/slack.d.ts.map +1 -0
  116. package/dist/repositories/slack.js +150 -0
  117. package/dist/repositories/slack.js.map +1 -0
  118. package/dist/repositories/tasks.d.ts +24 -0
  119. package/dist/repositories/tasks.d.ts.map +1 -0
  120. package/dist/repositories/tasks.js +194 -0
  121. package/dist/repositories/tasks.js.map +1 -0
  122. package/dist/retention.d.ts +38 -0
  123. package/dist/retention.d.ts.map +1 -0
  124. package/dist/retention.js +53 -0
  125. package/dist/retention.js.map +1 -0
  126. package/dist/runtime.d.ts +10 -0
  127. package/dist/runtime.d.ts.map +1 -0
  128. package/dist/runtime.js +13 -0
  129. package/dist/runtime.js.map +1 -0
  130. package/dist/server.d.ts +41 -0
  131. package/dist/server.d.ts.map +1 -0
  132. package/dist/server.js +138 -0
  133. package/dist/server.js.map +1 -0
  134. package/dist/tasks/JiraProvider.d.ts +27 -0
  135. package/dist/tasks/JiraProvider.d.ts.map +1 -0
  136. package/dist/tasks/JiraProvider.js +79 -0
  137. package/dist/tasks/JiraProvider.js.map +1 -0
  138. package/drizzle/20260622175812_flashy_maginty/migration.sql +689 -0
  139. package/drizzle/20260622175812_flashy_maginty/snapshot.json +8318 -0
  140. package/drizzle/20260623172634_loud_wallop/migration.sql +11 -0
  141. package/drizzle/20260623172634_loud_wallop/snapshot.json +8439 -0
  142. package/drizzle/20260623174706_acoustic_zemo/migration.sql +16 -0
  143. package/drizzle/20260623174706_acoustic_zemo/snapshot.json +8506 -0
  144. package/drizzle/20260623184400_silent_cardiac/migration.sql +24 -0
  145. package/drizzle/20260623184400_silent_cardiac/snapshot.json +8639 -0
  146. package/drizzle/20260623205323_quick_arclight/migration.sql +1 -0
  147. package/drizzle/20260623205323_quick_arclight/snapshot.json +8963 -0
  148. package/drizzle/20260623221910_black_zombie/migration.sql +22 -0
  149. package/drizzle/20260623221910_black_zombie/snapshot.json +9189 -0
  150. package/drizzle/20260624131343_far_lily_hollister/migration.sql +3 -0
  151. package/drizzle/20260624131343_far_lily_hollister/snapshot.json +9228 -0
  152. package/drizzle/20260624135452_tiny_norman_osborn/migration.sql +11 -0
  153. package/drizzle/20260624135452_tiny_norman_osborn/snapshot.json +9126 -0
  154. package/drizzle/20260624140138_wandering_avengers/migration.sql +1 -0
  155. package/drizzle/20260624140138_wandering_avengers/snapshot.json +9045 -0
  156. package/package.json +62 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Igor Savin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ import type { AppConfig } from '@cat-factory/server';
2
+ export declare function loadNodeConfig(env: NodeJS.ProcessEnv): AppConfig;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAgC,MAAM,qBAAqB,CAAA;AA8FlF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAqOhE"}
package/dist/config.js ADDED
@@ -0,0 +1,297 @@
1
+ import { ALL_SUBSCRIPTION_VENDORS, effectiveCatalog, resolveModelRef, } from '@cat-factory/kernel';
2
+ import { DEFAULT_SPEND_PRICING, modelCostResolver } from '@cat-factory/spend';
3
+ // Translate the Node process environment into the shared AppConfig contract. This is
4
+ // the Node analogue of the Worker's `loadConfig(env)`: same SHAPE, different source.
5
+ // Integrations (GitHub/documents/tasks/environments/runners/fragment-library) default
6
+ // to disabled in this MVP; the core (board/workspaces/pipelines/executions/spend +
7
+ // auth) is fully configured from env.
8
+ const MIN_SESSION_SECRET_LENGTH = 32;
9
+ const PRODUCTION_ENVIRONMENTS = new Set(['production', 'prod', 'staging']);
10
+ function num(value) {
11
+ if (value === undefined || value.trim() === '')
12
+ return undefined;
13
+ const n = Number(value);
14
+ return Number.isFinite(n) ? n : undefined;
15
+ }
16
+ function csv(value) {
17
+ return (value ?? '')
18
+ .split(',')
19
+ .map((s) => s.trim())
20
+ .filter(Boolean);
21
+ }
22
+ // The task sources the Node facade can serve, mirroring the Worker's `ALL_SOURCES`.
23
+ // GitHub issues reuse the workspace's installed GitHub App (wired in the container
24
+ // only when a GitHub client is available); Jira carries its own per-workspace creds.
25
+ const NODE_TASK_SOURCES = ['jira', 'github'];
26
+ const ALL_DOCUMENT_SOURCES = ['confluence', 'notion', 'github'];
27
+ /** Parse the comma-separated `DOCUMENT_SOURCES` allow-list, defaulting to all. */
28
+ function parseDocumentSources(raw) {
29
+ const requested = csv(raw).map((s) => s.toLowerCase());
30
+ if (requested.length === 0)
31
+ return [...ALL_DOCUMENT_SOURCES];
32
+ const selected = ALL_DOCUMENT_SOURCES.filter((s) => requested.includes(s));
33
+ return selected.length > 0 ? selected : [...ALL_DOCUMENT_SOURCES];
34
+ }
35
+ /**
36
+ * Document-source integration config, mirroring the Worker's `loadDocumentsConfig`:
37
+ * always on (tenants connect Notion/Confluence/GitHub-docs through the UI), with the
38
+ * shared ENCRYPTION_KEY backing per-workspace credential encryption at rest. The
39
+ * planner defaults to LLM mode; the container only wires a model provider when one is
40
+ * configured, so absent that the planner degrades to its deterministic heading parser.
41
+ */
42
+ function loadDocumentsConfig(env) {
43
+ const encryptionKey = env.ENCRYPTION_KEY?.trim();
44
+ if (!encryptionKey) {
45
+ throw new Error('ENCRYPTION_KEY is required: the document-source integration (Notion, Confluence, …) ' +
46
+ 'encrypts per-workspace source credentials at rest. Set it to a base64-encoded key of ' +
47
+ 'at least 32 bytes.');
48
+ }
49
+ return {
50
+ enabled: true,
51
+ sources: parseDocumentSources(env.DOCUMENT_SOURCES),
52
+ planner: env.DOCUMENT_PLANNER?.trim() === 'headings' ? 'headings' : 'llm',
53
+ encryptionKey,
54
+ };
55
+ }
56
+ /**
57
+ * Task-source integration config, mirroring the Worker's `loadTasksConfig`: always on
58
+ * (tenants connect their own trackers through the UI, so there is no enable flag), with
59
+ * a mandatory encryption key so credentials are never stored in plaintext. The key is
60
+ * missing → fail loudly at config load rather than silently disabling the feature.
61
+ * `TASK_SOURCES` narrows the registered providers (defaults to all Node-supported ones).
62
+ */
63
+ function loadTasksConfig(env) {
64
+ // The shared ENCRYPTION_KEY backs every integration (the cipher domain-separates per
65
+ // integration via its HKDF `info`, so one key safely backs them all).
66
+ const encryptionKey = env.ENCRYPTION_KEY?.trim();
67
+ if (!encryptionKey) {
68
+ throw new Error('ENCRYPTION_KEY is required: the task-source integration (Jira, …) encrypts ' +
69
+ 'per-workspace source credentials at rest. Set it to a base64-encoded key of at ' +
70
+ 'least 32 bytes.');
71
+ }
72
+ const requested = csv(env.TASK_SOURCES).map((s) => s.toLowerCase());
73
+ const sources = requested.length > 0
74
+ ? NODE_TASK_SOURCES.filter((s) => requested.includes(s))
75
+ : [...NODE_TASK_SOURCES];
76
+ return {
77
+ enabled: true,
78
+ sources: sources.length > 0 ? sources : [...NODE_TASK_SOURCES],
79
+ encryptionKey,
80
+ };
81
+ }
82
+ export function loadNodeConfig(env) {
83
+ // Deployment-level capabilities: direct keys are per-workspace (resolved at run time
84
+ // from the DB pool), so none are known here; Cloudflare Workers AI is opt-in over
85
+ // REST (account id + API token). The per-workspace `/models` endpoint recomputes
86
+ // selectability against each workspace's configured keys + subscriptions.
87
+ const caps = {
88
+ directProviders: new Set(),
89
+ subscriptionVendors: new Set(ALL_SUBSCRIPTION_VENDORS),
90
+ cloudflareEnabled: !!(env.CLOUDFLARE_ACCOUNT_ID && env.CLOUDFLARE_API_TOKEN),
91
+ };
92
+ // Default unpinned agents to Qwen (the Cloudflare flavour when enabled, upgraded to
93
+ // direct DashScope per-workspace by the executor when a Qwen key is configured); the
94
+ // agentic kinds default to GLM-5.2 — mirroring the Worker's routing.
95
+ const qwenDefault = resolveModelRef('qwen', caps);
96
+ const defaultConfig = {
97
+ ref: {
98
+ provider: env.AGENT_DEFAULT_PROVIDER ?? qwenDefault?.provider ?? 'workers-ai',
99
+ model: env.AGENT_DEFAULT_MODEL ?? qwenDefault?.model ?? '@cf/qwen/qwen3-30b-a3b-fp8',
100
+ },
101
+ temperature: num(env.AGENT_DEFAULT_TEMPERATURE) ?? 0.4,
102
+ maxOutputTokens: num(env.AGENT_MAX_OUTPUT_TOKENS) ?? 5000,
103
+ };
104
+ const agenticDefault = {
105
+ ref: { provider: 'workers-ai', model: '@cf/zai-org/glm-5.2' },
106
+ temperature: num(env.AGENT_DEFAULT_TEMPERATURE) ?? 0.3,
107
+ maxOutputTokens: num(env.AGENT_MAX_OUTPUT_TOKENS) ?? 5000,
108
+ };
109
+ // Companions (reviewer / spec-companion / architect-companion) return their whole
110
+ // verdict — rating + summary + per-item comments — as ONE inline JSON reply. On a
111
+ // reasoning model the <think> tokens share the output budget, so the 5000 cap can
112
+ // truncate the JSON mid-comment, leaving it unparseable. Give companions a larger
113
+ // budget so the verdict fits (mirrors the Worker's routing).
114
+ const companionDefault = {
115
+ ref: { provider: 'workers-ai', model: '@cf/zai-org/glm-5.2' },
116
+ temperature: num(env.AGENT_DEFAULT_TEMPERATURE) ?? 0.3,
117
+ maxOutputTokens: num(env.AGENT_MAX_OUTPUT_TOKENS) ?? 12000,
118
+ };
119
+ const sessionSecret = env.AUTH_SESSION_SECRET?.trim() ?? '';
120
+ // The GitHub App (private key + app id) backs container-agent runs: it mints the
121
+ // short-lived push token the harness clones/pushes with. Enable the integration
122
+ // only when both are present (the container executor also requires it — see
123
+ // container.ts), so a partial config doesn't half-enable repo-operating steps.
124
+ const githubAppId = env.GITHUB_APP_ID?.trim() ?? '';
125
+ const githubAppConfigured = githubAppId !== '' && (env.GITHUB_APP_PRIVATE_KEY?.trim() ?? '') !== '';
126
+ // Self-hosted runner pools encrypt their scheduler credentials at rest; opt-in via
127
+ // the enable flag, sealed with the shared ENCRYPTION_KEY (mirroring the Worker).
128
+ const runnersEncryptionKey = env.ENCRYPTION_KEY?.trim() ?? '';
129
+ // Slack notification transport: opt-in (SLACK_ENABLED), the per-account bot token
130
+ // sealed with the shared ENCRYPTION_KEY. OAuth credentials are optional (manual
131
+ // bot-token onboarding works without them); when set they enable "Add to Slack".
132
+ const slackEnabled = env.SLACK_ENABLED?.trim() === 'true';
133
+ const slackEncryptionKey = env.ENCRYPTION_KEY?.trim() ?? '';
134
+ const slackClientId = env.SLACK_CLIENT_ID?.trim() ?? '';
135
+ const slackClientSecret = env.SLACK_CLIENT_SECRET?.trim() ?? '';
136
+ const slackRedirectUrl = env.SLACK_REDIRECT_URL?.trim() ?? '';
137
+ const slackOAuth = slackClientId && slackClientSecret && slackRedirectUrl
138
+ ? { clientId: slackClientId, clientSecret: slackClientSecret, redirectUrl: slackRedirectUrl }
139
+ : undefined;
140
+ const clientId = env.GITHUB_OAUTH_CLIENT_ID?.trim() ?? '';
141
+ const clientSecret = env.GITHUB_OAUTH_CLIENT_SECRET?.trim() ?? '';
142
+ const googleClientId = env.GOOGLE_OAUTH_CLIENT_ID?.trim() ?? '';
143
+ const googleClientSecret = env.GOOGLE_OAUTH_CLIENT_SECRET?.trim() ?? '';
144
+ const environment = env.ENVIRONMENT?.trim().toLowerCase() ?? '';
145
+ const ttlHours = num(env.AUTH_SESSION_TTL_HOURS);
146
+ const strongSecret = sessionSecret.length >= MIN_SESSION_SECRET_LENGTH;
147
+ const githubEnabled = clientId !== '' && clientSecret !== '' && strongSecret;
148
+ const googleEnabled = googleClientId !== '' && googleClientSecret !== '' && strongSecret;
149
+ const passwordEnabled = env.AUTH_PASSWORD_ENABLED?.trim() === 'true' && strongSecret;
150
+ const devOpen = env.AUTH_DEV_OPEN?.trim() === 'true' && !PRODUCTION_ENVIRONMENTS.has(environment);
151
+ // Fail fast on the silent-brick footgun: OAuth credentials are set (so real auth is
152
+ // intended) but the session secret is missing/too short, which would disable the auth
153
+ // gate and — with no dev-open fallback — make it fail closed, 503-ing every protected
154
+ // route with no hint why. Refuse to boot with a clear message instead.
155
+ if (clientId !== '' &&
156
+ clientSecret !== '' &&
157
+ sessionSecret.length < MIN_SESSION_SECRET_LENGTH &&
158
+ !devOpen) {
159
+ throw new Error(`AUTH_SESSION_SECRET must be at least ${MIN_SESSION_SECRET_LENGTH} characters when GitHub OAuth is configured ` +
160
+ `(got ${sessionSecret.length}). Set a longer secret or enable AUTH_DEV_OPEN in a non-production environment.`);
161
+ }
162
+ const spend = {
163
+ ...DEFAULT_SPEND_PRICING,
164
+ currency: env.SPEND_CURRENCY?.trim() || DEFAULT_SPEND_PRICING.currency,
165
+ monthlyLimit: num(env.SPEND_MONTHLY_LIMIT) ?? DEFAULT_SPEND_PRICING.monthlyLimit,
166
+ };
167
+ return {
168
+ agents: {
169
+ routing: {
170
+ default: defaultConfig,
171
+ byKind: {
172
+ architect: agenticDefault,
173
+ coder: agenticDefault,
174
+ reviewer: companionDefault,
175
+ 'spec-companion': companionDefault,
176
+ 'architect-companion': companionDefault,
177
+ },
178
+ },
179
+ resolveBlockModel: (modelId) => resolveModelRef(modelId, caps),
180
+ },
181
+ // Surface each model's informational list cost in the picker (from spend pricing).
182
+ models: effectiveCatalog(caps, modelCostResolver(spend)),
183
+ execution: {
184
+ decisionTimeout: env.DECISION_TIMEOUT?.trim() || '24 hours',
185
+ jobPollInterval: env.JOB_POLL_INTERVAL?.trim() || '15 seconds',
186
+ jobMaxPolls: num(env.JOB_MAX_POLLS) ?? 280,
187
+ jobPollFailureTolerance: num(env.JOB_POLL_FAILURE_TOLERANCE) ?? 6,
188
+ ciPollInterval: env.CI_POLL_INTERVAL?.trim() || '30 seconds',
189
+ ciMaxPolls: num(env.CI_MAX_POLLS) ?? 120,
190
+ containerMaxAgeMs: Math.max(75, num(env.CONTAINER_MAX_AGE_MINUTES) ?? 90) * 60_000,
191
+ },
192
+ spend,
193
+ github: {
194
+ enabled: githubAppConfigured,
195
+ appId: env.GITHUB_APP_ID?.trim() ?? '',
196
+ appSlug: env.GITHUB_APP_SLUG?.trim() ?? '',
197
+ apiBase: env.GITHUB_API_BASE?.trim() || 'https://api.github.com',
198
+ setupRedirectUrl: env.GITHUB_SETUP_REDIRECT_URL?.trim() || '/',
199
+ webhookSecret: env.GITHUB_WEBHOOK_SECRET ?? '',
200
+ },
201
+ auth: {
202
+ enabled: githubEnabled || googleEnabled || passwordEnabled,
203
+ devOpen,
204
+ githubEnabled,
205
+ clientId,
206
+ clientSecret,
207
+ sessionSecret,
208
+ apiBase: env.GITHUB_API_BASE?.trim() || 'https://api.github.com',
209
+ oauthBase: env.GITHUB_OAUTH_BASE?.trim() || 'https://github.com',
210
+ sessionTtlMs: (ttlHours !== undefined && ttlHours > 0 ? ttlHours : 168) * 60 * 60 * 1000,
211
+ successRedirectUrl: env.AUTH_SUCCESS_REDIRECT_URL?.trim() || '',
212
+ callbackUrl: env.AUTH_CALLBACK_URL?.trim() || '',
213
+ passwordEnabled,
214
+ ...(googleEnabled
215
+ ? {
216
+ google: {
217
+ clientId: googleClientId,
218
+ clientSecret: googleClientSecret,
219
+ redirectUrl: env.GOOGLE_OAUTH_REDIRECT_URL?.trim() || '',
220
+ },
221
+ }
222
+ : {}),
223
+ allowedEmailDomains: csv(env.AUTH_ALLOWED_EMAIL_DOMAINS).map((d) => d.toLowerCase()),
224
+ allowedLogins: csv(env.AUTH_ALLOWED_LOGINS).map((l) => l.toLowerCase()),
225
+ allowedOrgs: csv(env.AUTH_ALLOWED_ORGS).map((o) => o.toLowerCase()),
226
+ allowedRedirectOrigins: csv(env.AUTH_ALLOWED_REDIRECT_ORIGINS).map((o) => {
227
+ try {
228
+ return new URL(o).origin;
229
+ }
230
+ catch {
231
+ return o;
232
+ }
233
+ }),
234
+ },
235
+ email: env.EMAIL_ENABLED?.trim() === 'true' && env.ENCRYPTION_KEY?.trim()
236
+ ? {
237
+ enabled: true,
238
+ encryptionKey: env.ENCRYPTION_KEY.trim(),
239
+ appBaseUrl: env.APP_BASE_URL?.trim() || env.AUTH_SUCCESS_REDIRECT_URL?.trim() || '',
240
+ }
241
+ : {
242
+ enabled: false,
243
+ appBaseUrl: env.APP_BASE_URL?.trim() || env.AUTH_SUCCESS_REDIRECT_URL?.trim() || '',
244
+ },
245
+ // Document-source integration: the providers (Confluence/Notion/GitHub-docs) are
246
+ // the shared `@cat-factory/integrations` fetch shells, wired in the container
247
+ // exactly like the Worker's `selectDocumentsDeps`. Always on (the shared
248
+ // ENCRYPTION_KEY backs credential encryption at rest).
249
+ documents: loadDocumentsConfig(env),
250
+ tasks: loadTasksConfig(env),
251
+ // Ephemeral-environment provider integration: opt-in (a tenant rolls its own
252
+ // environment-management API), gated on ENVIRONMENTS_ENABLED + the shared
253
+ // ENCRYPTION_KEY (credentials are encrypted at rest), mirroring the Worker.
254
+ environments: env.ENVIRONMENTS_ENABLED === 'true' && env.ENCRYPTION_KEY?.trim()
255
+ ? { enabled: true, encryptionKey: env.ENCRYPTION_KEY.trim() }
256
+ : { enabled: false },
257
+ runners: runnersEncryptionKey
258
+ ? { enabled: true, encryptionKey: runnersEncryptionKey }
259
+ : { enabled: false },
260
+ slack: slackEnabled && slackEncryptionKey
261
+ ? {
262
+ enabled: true,
263
+ encryptionKey: slackEncryptionKey,
264
+ ...(slackOAuth ? { oauth: slackOAuth } : {}),
265
+ }
266
+ : { enabled: false },
267
+ retention: {
268
+ tokenUsageMs: (num(env.TOKEN_USAGE_RETENTION_DAYS) ?? 395) * 24 * 60 * 60 * 1000,
269
+ rateLimitMs: (num(env.GITHUB_RATE_LIMIT_RETENTION_DAYS) ?? 7) * 24 * 60 * 60 * 1000,
270
+ commitMs: (num(env.GITHUB_COMMIT_RETENTION_DAYS) ?? 90) * 24 * 60 * 60 * 1000,
271
+ // Heavy full per-call prompt/response; pruned aggressively (default 3 days).
272
+ llmCallMetricsMs: (num(env.LLM_CALL_METRICS_RETENTION_DAYS) ?? 3) * 24 * 60 * 60 * 1000,
273
+ },
274
+ // Prompt-fragment library (ADR 0006): opt-in (`PROMPT_LIBRARY_ENABLED=true`),
275
+ // needs no encryption key (fragments are not secrets). Mirrors the Worker's
276
+ // mapping; `PROMPT_LIBRARY_SELECTOR=llm` ranks per run, else the deterministic
277
+ // tag matcher (which also backs the `llm` selector's graceful fallback).
278
+ fragmentLibrary: {
279
+ enabled: env.PROMPT_LIBRARY_ENABLED?.trim() === 'true',
280
+ selector: env.PROMPT_LIBRARY_SELECTOR?.trim() === 'llm' ? 'llm' : 'deterministic',
281
+ },
282
+ // Recording the complete prompts is on by default; opt out with
283
+ // `LLM_RECORD_PROMPTS=false` to keep the numeric telemetry but drop the prompt body.
284
+ observability: { recordPrompts: env.LLM_RECORD_PROMPTS?.trim() !== 'false' },
285
+ // Optional Langfuse trace sink: off unless `LANGFUSE_ENABLED=true` AND both keys are
286
+ // present (a half-configured sink silently does nothing). Mirrors the Worker mapping.
287
+ langfuse: {
288
+ enabled: env.LANGFUSE_ENABLED?.trim() === 'true' &&
289
+ !!env.LANGFUSE_PUBLIC_KEY?.trim() &&
290
+ !!env.LANGFUSE_SECRET_KEY?.trim(),
291
+ publicKey: env.LANGFUSE_PUBLIC_KEY?.trim(),
292
+ secretKey: env.LANGFUSE_SECRET_KEY?.trim(),
293
+ baseUrl: env.LANGFUSE_BASE_URL?.trim() || undefined,
294
+ },
295
+ };
296
+ }
297
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { type GitHubClient, type GitHubInstallationRepository } from '@cat-factory/kernel';
2
+ import { type CoreDependencies } from '@cat-factory/orchestration';
3
+ import { type AppConfig, type ResolveRunnerTransport, type ServerContainer } from '@cat-factory/server';
4
+ import type { PgBoss } from 'pg-boss';
5
+ import type { DrizzleDb } from './db/client.js';
6
+ import { type NodeRealtimeHub } from './realtime.js';
7
+ import { createDrizzleRepositories } from './repositories/drizzle.js';
8
+ export interface NodeContainerOptions {
9
+ /** The Drizzle/Postgres client (the single persistence layer). */
10
+ db: DrizzleDb;
11
+ /**
12
+ * Pre-built repositories; defaults to building them from {@link db}. Lets the caller
13
+ * (e.g. {@link start}) share one set with the retention sweeper rather than rebuild.
14
+ */
15
+ repos?: ReturnType<typeof createDrizzleRepositories>;
16
+ /**
17
+ * Started pg-boss instance for durable execution. When present the container wires
18
+ * a {@link PgBossWorkRunner}; otherwise runs fall back to the engine's NoopWorkRunner
19
+ * (the caller drives runs itself — e.g. tests).
20
+ */
21
+ boss?: PgBoss;
22
+ /** Pre-resolved config; defaults to `loadNodeConfig(env)`. */
23
+ config?: AppConfig;
24
+ /** Environment source; defaults to `process.env`. */
25
+ env?: NodeJS.ProcessEnv;
26
+ /** Override core dependencies — used by tests (e.g. a fake agent executor). */
27
+ overrides?: Partial<CoreDependencies>;
28
+ /**
29
+ * Override the runner backend the container-agent steps dispatch to. When provided
30
+ * (even as `null`) it REPLACES the default self-hosted-pool resolution, so a sibling
31
+ * facade can supply its own transport (e.g. the local-mode Docker transport) without
32
+ * registering a runner pool. Undefined → the default Node behaviour (resolve a
33
+ * workspace's self-hosted pool when runner pools are enabled).
34
+ */
35
+ resolveTransport?: ResolveRunnerTransport | null;
36
+ /**
37
+ * Override how the container executor mints the push/clone token. When provided it
38
+ * REPLACES the GitHub-App token mint, so a sibling facade can authenticate with a
39
+ * static credential instead of an App installation (e.g. a PAT in local mode). The
40
+ * `installationId` argument is then ignored. Undefined → mint via the GitHub App
41
+ * (requires `GITHUB_APP_PRIVATE_KEY`).
42
+ */
43
+ mintInstallationToken?: (installationId: number) => Promise<string>;
44
+ /**
45
+ * A GitHub client used to wire the CI gate + the merge / mergeability providers
46
+ * (so a run gates on real CI and merges for real). When provided, the
47
+ * `ciStatusProvider`, `mergeabilityProvider` and `pullRequestMerger` are wired from
48
+ * it + the resolved repo target. Undefined → those gates pass through (the existing
49
+ * Node behaviour). The local facade passes a PAT-backed client.
50
+ */
51
+ githubClient?: GitHubClient;
52
+ /**
53
+ * Override the GitHub installation repository. When provided it REPLACES the default
54
+ * Drizzle one, so a sibling facade can wrap it — e.g. local mode decorates it to
55
+ * auto-provision a synthetic per-workspace installation for its PAT, since there is no
56
+ * GitHub-App connect flow. Undefined → the default Drizzle repository over {@link db}.
57
+ */
58
+ githubInstallationRepository?: GitHubInstallationRepository;
59
+ /**
60
+ * Force the Cloudflare-AI opt-in flag (the cross-runtime conformance suite forces it
61
+ * off for parity). Undefined → derived from the REST credentials being present.
62
+ */
63
+ cloudflareModelsEnabled?: boolean;
64
+ /**
65
+ * The real-time subscriber registry. When provided, the container wires a
66
+ * {@link NodeEventPublisher} (so the engine pushes execution/board/notification events
67
+ * to subscribed browsers) and composes an in-app notification channel. `start()`
68
+ * creates the hub and attaches it to the HTTP server via {@link attachRealtime};
69
+ * `createServer`/tests leave it unset and the engine falls back to the no-op publisher
70
+ * (no live push), exactly as before.
71
+ */
72
+ realtimeHub?: NodeRealtimeHub;
73
+ }
74
+ /**
75
+ * The Node composition root: assemble the framework-agnostic domain `Core` with
76
+ * Drizzle/Postgres repositories + Node implementations of the runtime ports, then
77
+ * attach the shared-controller extras (`config`, the kind-spanning agent-run repo,
78
+ * the runtime gateways). The same persistence is used in dev, test and prod — tests
79
+ * run against a real Postgres, exactly as the Worker runs against a real D1.
80
+ *
81
+ * Repo-operating agent steps (coder, blueprints, merger, …) run in a container
82
+ * dispatched to a workspace's self-hosted runner pool — the shared
83
+ * `ContainerAgentExecutor`, exactly as on the Worker. When the prerequisites (GitHub
84
+ * App, `PUBLIC_URL`, `AUTH_SESSION_SECRET`, `ENCRYPTION_KEY`) are absent the
85
+ * composite still serves inline kinds but fails container kinds loudly.
86
+ */
87
+ export declare function buildNodeContainer(options: NodeContainerOptions): ServerContainer;
88
+ //# sourceMappingURL=container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AA0BA,OAAO,EAKL,KAAK,YAAY,EACjB,KAAK,4BAA4B,EAQlC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,KAAK,gBAAgB,EAAc,MAAM,4BAA4B,CAAA;AAE9E,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EAsBrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAO/C,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAqBxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAA;AAkMrE,MAAM,WAAW,oBAAoB;IACnC,kEAAkE;IAClE,EAAE,EAAE,SAAS,CAAA;IACb;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAA;IACpD;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACrC;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAA;IAChD;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACnE;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B;;;;;OAKG;IACH,4BAA4B,CAAC,EAAE,4BAA4B,CAAA;IAC3D;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,eAAe,CAAA;CAC9B;AA6UD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,GAAG,eAAe,CAkcjF"}