@cat-factory/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.
- package/LICENSE +21 -0
- package/dist/agents/CompositeAgentExecutor.d.ts +39 -0
- package/dist/agents/CompositeAgentExecutor.d.ts.map +1 -0
- package/dist/agents/CompositeAgentExecutor.js +169 -0
- package/dist/agents/CompositeAgentExecutor.js.map +1 -0
- package/dist/agents/ContainerAgentExecutor.d.ts +235 -0
- package/dist/agents/ContainerAgentExecutor.d.ts.map +1 -0
- package/dist/agents/ContainerAgentExecutor.js +825 -0
- package/dist/agents/ContainerAgentExecutor.js.map +1 -0
- package/dist/agents/ContainerRepoBootstrapper.d.ts +78 -0
- package/dist/agents/ContainerRepoBootstrapper.d.ts.map +1 -0
- package/dist/agents/ContainerRepoBootstrapper.js +279 -0
- package/dist/agents/ContainerRepoBootstrapper.js.map +1 -0
- package/dist/agents/ModelRouter.d.ts +69 -0
- package/dist/agents/ModelRouter.d.ts.map +1 -0
- package/dist/agents/ModelRouter.js +84 -0
- package/dist/agents/ModelRouter.js.map +1 -0
- package/dist/agents/RunnerJobClient.d.ts +41 -0
- package/dist/agents/RunnerJobClient.d.ts.map +1 -0
- package/dist/agents/RunnerJobClient.js +43 -0
- package/dist/agents/RunnerJobClient.js.map +1 -0
- package/dist/agents/modelProviderResolver.d.ts +33 -0
- package/dist/agents/modelProviderResolver.d.ts.map +1 -0
- package/dist/agents/modelProviderResolver.js +48 -0
- package/dist/agents/modelProviderResolver.js.map +1 -0
- package/dist/agents/providerCapabilities.d.ts +22 -0
- package/dist/agents/providerCapabilities.d.ts.map +1 -0
- package/dist/agents/providerCapabilities.js +43 -0
- package/dist/agents/providerCapabilities.js.map +1 -0
- package/dist/agents/resolveRepoTarget.d.ts +33 -0
- package/dist/agents/resolveRepoTarget.d.ts.map +1 -0
- package/dist/agents/resolveRepoTarget.js +81 -0
- package/dist/agents/resolveRepoTarget.js.map +1 -0
- package/dist/app.d.ts +12 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +102 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/GitHubOAuth.d.ts +39 -0
- package/dist/auth/GitHubOAuth.d.ts.map +1 -0
- package/dist/auth/GitHubOAuth.js +90 -0
- package/dist/auth/GitHubOAuth.js.map +1 -0
- package/dist/auth/GoogleOAuth.d.ts +35 -0
- package/dist/auth/GoogleOAuth.d.ts.map +1 -0
- package/dist/auth/GoogleOAuth.js +66 -0
- package/dist/auth/GoogleOAuth.js.map +1 -0
- package/dist/auth/middleware.d.ts +15 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +63 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/signing.d.ts +50 -0
- package/dist/auth/signing.d.ts.map +1 -0
- package/dist/auth/signing.js +96 -0
- package/dist/auth/signing.js.map +1 -0
- package/dist/auth/wsTicket.d.ts +34 -0
- package/dist/auth/wsTicket.d.ts.map +1 -0
- package/dist/auth/wsTicket.js +50 -0
- package/dist/auth/wsTicket.js.map +1 -0
- package/dist/config/types.d.ts +294 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/url-safety.d.ts +8 -0
- package/dist/config/url-safety.d.ts.map +1 -0
- package/dist/config/url-safety.js +11 -0
- package/dist/config/url-safety.js.map +1 -0
- package/dist/containers/ContainerSessionService.d.ts +67 -0
- package/dist/containers/ContainerSessionService.d.ts.map +1 -0
- package/dist/containers/ContainerSessionService.js +44 -0
- package/dist/containers/ContainerSessionService.js.map +1 -0
- package/dist/crypto/WebCryptoPasswordHasher.d.ts +9 -0
- package/dist/crypto/WebCryptoPasswordHasher.d.ts.map +1 -0
- package/dist/crypto/WebCryptoPasswordHasher.js +67 -0
- package/dist/crypto/WebCryptoPasswordHasher.js.map +1 -0
- package/dist/crypto/WebCryptoPersonalSecretCipher.d.ts +6 -0
- package/dist/crypto/WebCryptoPersonalSecretCipher.d.ts.map +1 -0
- package/dist/crypto/WebCryptoPersonalSecretCipher.js +57 -0
- package/dist/crypto/WebCryptoPersonalSecretCipher.js.map +1 -0
- package/dist/crypto/WebCryptoSecretCipher.d.ts +23 -0
- package/dist/crypto/WebCryptoSecretCipher.d.ts.map +1 -0
- package/dist/crypto/WebCryptoSecretCipher.js +60 -0
- package/dist/crypto/WebCryptoSecretCipher.js.map +1 -0
- package/dist/crypto/encoding.d.ts +14 -0
- package/dist/crypto/encoding.d.ts.map +1 -0
- package/dist/crypto/encoding.js +58 -0
- package/dist/crypto/encoding.js.map +1 -0
- package/dist/events/FanOutEventPublisher.d.ts +32 -0
- package/dist/events/FanOutEventPublisher.d.ts.map +1 -0
- package/dist/events/FanOutEventPublisher.js +76 -0
- package/dist/events/FanOutEventPublisher.js.map +1 -0
- package/dist/events/InAppNotificationChannel.d.ts +20 -0
- package/dist/events/InAppNotificationChannel.d.ts.map +1 -0
- package/dist/events/InAppNotificationChannel.js +23 -0
- package/dist/events/InAppNotificationChannel.js.map +1 -0
- package/dist/github/FetchGitHubClient.d.ts +72 -0
- package/dist/github/FetchGitHubClient.d.ts.map +1 -0
- package/dist/github/FetchGitHubClient.js +485 -0
- package/dist/github/FetchGitHubClient.js.map +1 -0
- package/dist/github/FetchGitHubProvisioningClient.d.ts +13 -0
- package/dist/github/FetchGitHubProvisioningClient.d.ts.map +1 -0
- package/dist/github/FetchGitHubProvisioningClient.js +59 -0
- package/dist/github/FetchGitHubProvisioningClient.js.map +1 -0
- package/dist/github/GitHubAppAuth.d.ts +30 -0
- package/dist/github/GitHubAppAuth.d.ts.map +1 -0
- package/dist/github/GitHubAppAuth.js +95 -0
- package/dist/github/GitHubAppAuth.js.map +1 -0
- package/dist/github/GitHubAppRegistry.d.ts +57 -0
- package/dist/github/GitHubAppRegistry.d.ts.map +1 -0
- package/dist/github/GitHubAppRegistry.js +51 -0
- package/dist/github/GitHubAppRegistry.js.map +1 -0
- package/dist/github/GitHubCiStatusProvider.d.ts +21 -0
- package/dist/github/GitHubCiStatusProvider.d.ts.map +1 -0
- package/dist/github/GitHubCiStatusProvider.js +39 -0
- package/dist/github/GitHubCiStatusProvider.js.map +1 -0
- package/dist/github/GitHubMergeabilityProvider.d.ts +26 -0
- package/dist/github/GitHubMergeabilityProvider.d.ts.map +1 -0
- package/dist/github/GitHubMergeabilityProvider.js +38 -0
- package/dist/github/GitHubMergeabilityProvider.js.map +1 -0
- package/dist/github/GitHubPullRequestMerger.d.ts +23 -0
- package/dist/github/GitHubPullRequestMerger.d.ts.map +1 -0
- package/dist/github/GitHubPullRequestMerger.js +38 -0
- package/dist/github/GitHubPullRequestMerger.js.map +1 -0
- package/dist/github/WebCryptoWebhookVerifier.d.ts +9 -0
- package/dist/github/WebCryptoWebhookVerifier.d.ts.map +1 -0
- package/dist/github/WebCryptoWebhookVerifier.js +40 -0
- package/dist/github/WebCryptoWebhookVerifier.js.map +1 -0
- package/dist/github/ensureWorkBranch.d.ts +26 -0
- package/dist/github/ensureWorkBranch.d.ts.map +1 -0
- package/dist/github/ensureWorkBranch.js +97 -0
- package/dist/github/ensureWorkBranch.js.map +1 -0
- package/dist/github/state.d.ts +19 -0
- package/dist/github/state.d.ts.map +1 -0
- package/dist/github/state.js +55 -0
- package/dist/github/state.js.map +1 -0
- package/dist/http/authGate.d.ts +21 -0
- package/dist/http/authGate.d.ts.map +1 -0
- package/dist/http/authGate.js +77 -0
- package/dist/http/authGate.js.map +1 -0
- package/dist/http/cors.d.ts +13 -0
- package/dist/http/cors.d.ts.map +1 -0
- package/dist/http/cors.js +30 -0
- package/dist/http/cors.js.map +1 -0
- package/dist/http/env.d.ts +68 -0
- package/dist/http/env.d.ts.map +1 -0
- package/dist/http/env.js +2 -0
- package/dist/http/env.js.map +1 -0
- package/dist/http/errorHandler.d.ts +4 -0
- package/dist/http/errorHandler.d.ts.map +1 -0
- package/dist/http/errorHandler.js +33 -0
- package/dist/http/errorHandler.js.map +1 -0
- package/dist/http/params.d.ts +8 -0
- package/dist/http/params.d.ts.map +1 -0
- package/dist/http/params.js +13 -0
- package/dist/http/params.js.map +1 -0
- package/dist/http/validation.d.ts +12 -0
- package/dist/http/validation.d.ts.map +1 -0
- package/dist/http/validation.js +21 -0
- package/dist/http/validation.js.map +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/accounts/AccountController.d.ts +10 -0
- package/dist/modules/accounts/AccountController.d.ts.map +1 -0
- package/dist/modules/accounts/AccountController.js +197 -0
- package/dist/modules/accounts/AccountController.js.map +1 -0
- package/dist/modules/agentRuns/AgentRunController.d.ts +10 -0
- package/dist/modules/agentRuns/AgentRunController.d.ts.map +1 -0
- package/dist/modules/agentRuns/AgentRunController.js +65 -0
- package/dist/modules/agentRuns/AgentRunController.js.map +1 -0
- package/dist/modules/auth/AuthController.d.ts +12 -0
- package/dist/modules/auth/AuthController.d.ts.map +1 -0
- package/dist/modules/auth/AuthController.js +457 -0
- package/dist/modules/auth/AuthController.js.map +1 -0
- package/dist/modules/board/BoardController.d.ts +8 -0
- package/dist/modules/board/BoardController.d.ts.map +1 -0
- package/dist/modules/board/BoardController.js +89 -0
- package/dist/modules/board/BoardController.js.map +1 -0
- package/dist/modules/boardScan/BoardScanController.d.ts +10 -0
- package/dist/modules/boardScan/BoardScanController.d.ts.map +1 -0
- package/dist/modules/boardScan/BoardScanController.js +53 -0
- package/dist/modules/boardScan/BoardScanController.js.map +1 -0
- package/dist/modules/bootstrap/BootstrapController.d.ts +10 -0
- package/dist/modules/bootstrap/BootstrapController.d.ts.map +1 -0
- package/dist/modules/bootstrap/BootstrapController.js +75 -0
- package/dist/modules/bootstrap/BootstrapController.js.map +1 -0
- package/dist/modules/clarity/ClarityReviewController.d.ts +11 -0
- package/dist/modules/clarity/ClarityReviewController.d.ts.map +1 -0
- package/dist/modules/clarity/ClarityReviewController.js +97 -0
- package/dist/modules/clarity/ClarityReviewController.js.map +1 -0
- package/dist/modules/consensus/ConsensusController.d.ts +12 -0
- package/dist/modules/consensus/ConsensusController.d.ts.map +1 -0
- package/dist/modules/consensus/ConsensusController.js +23 -0
- package/dist/modules/consensus/ConsensusController.js.map +1 -0
- package/dist/modules/documents/DocumentSourceController.d.ts +10 -0
- package/dist/modules/documents/DocumentSourceController.d.ts.map +1 -0
- package/dist/modules/documents/DocumentSourceController.js +116 -0
- package/dist/modules/documents/DocumentSourceController.js.map +1 -0
- package/dist/modules/environments/EnvironmentController.d.ts +10 -0
- package/dist/modules/environments/EnvironmentController.d.ts.map +1 -0
- package/dist/modules/environments/EnvironmentController.js +95 -0
- package/dist/modules/environments/EnvironmentController.js.map +1 -0
- package/dist/modules/events/EventsController.d.ts +26 -0
- package/dist/modules/events/EventsController.d.ts.map +1 -0
- package/dist/modules/events/EventsController.js +56 -0
- package/dist/modules/events/EventsController.js.map +1 -0
- package/dist/modules/execution/ExecutionController.d.ts +10 -0
- package/dist/modules/execution/ExecutionController.d.ts.map +1 -0
- package/dist/modules/execution/ExecutionController.js +156 -0
- package/dist/modules/execution/ExecutionController.js.map +1 -0
- package/dist/modules/fragmentLibrary/FragmentLibraryController.d.ts +14 -0
- package/dist/modules/fragmentLibrary/FragmentLibraryController.d.ts.map +1 -0
- package/dist/modules/fragmentLibrary/FragmentLibraryController.js +128 -0
- package/dist/modules/fragmentLibrary/FragmentLibraryController.js.map +1 -0
- package/dist/modules/github/GitHubController.d.ts +12 -0
- package/dist/modules/github/GitHubController.d.ts.map +1 -0
- package/dist/modules/github/GitHubController.js +234 -0
- package/dist/modules/github/GitHubController.js.map +1 -0
- package/dist/modules/github/GitHubWebhookController.d.ts +13 -0
- package/dist/modules/github/GitHubWebhookController.d.ts.map +1 -0
- package/dist/modules/github/GitHubWebhookController.js +74 -0
- package/dist/modules/github/GitHubWebhookController.js.map +1 -0
- package/dist/modules/llmProxy/LlmProxyController.d.ts +18 -0
- package/dist/modules/llmProxy/LlmProxyController.d.ts.map +1 -0
- package/dist/modules/llmProxy/LlmProxyController.js +567 -0
- package/dist/modules/llmProxy/LlmProxyController.js.map +1 -0
- package/dist/modules/localModels/LocalModelEndpointController.d.ts +4 -0
- package/dist/modules/localModels/LocalModelEndpointController.d.ts.map +1 -0
- package/dist/modules/localModels/LocalModelEndpointController.js +58 -0
- package/dist/modules/localModels/LocalModelEndpointController.js.map +1 -0
- package/dist/modules/merge/MergePresetController.d.ts +9 -0
- package/dist/modules/merge/MergePresetController.d.ts.map +1 -0
- package/dist/modules/merge/MergePresetController.js +46 -0
- package/dist/modules/merge/MergePresetController.js.map +1 -0
- package/dist/modules/modelDefaults/ModelDefaultsController.d.ts +9 -0
- package/dist/modules/modelDefaults/ModelDefaultsController.d.ts.map +1 -0
- package/dist/modules/modelDefaults/ModelDefaultsController.js +32 -0
- package/dist/modules/modelDefaults/ModelDefaultsController.js.map +1 -0
- package/dist/modules/models/ModelController.d.ts +11 -0
- package/dist/modules/models/ModelController.d.ts.map +1 -0
- package/dist/modules/models/ModelController.js +38 -0
- package/dist/modules/models/ModelController.js.map +1 -0
- package/dist/modules/notifications/NotificationController.d.ts +13 -0
- package/dist/modules/notifications/NotificationController.d.ts.map +1 -0
- package/dist/modules/notifications/NotificationController.js +67 -0
- package/dist/modules/notifications/NotificationController.js.map +1 -0
- package/dist/modules/pipelines/PipelineController.d.ts +5 -0
- package/dist/modules/pipelines/PipelineController.d.ts.map +1 -0
- package/dist/modules/pipelines/PipelineController.js +46 -0
- package/dist/modules/pipelines/PipelineController.js.map +1 -0
- package/dist/modules/promptFragments/PromptFragmentController.d.ts +11 -0
- package/dist/modules/promptFragments/PromptFragmentController.d.ts.map +1 -0
- package/dist/modules/promptFragments/PromptFragmentController.js +18 -0
- package/dist/modules/promptFragments/PromptFragmentController.js.map +1 -0
- package/dist/modules/providers/ApiKeyController.d.ts +13 -0
- package/dist/modules/providers/ApiKeyController.d.ts.map +1 -0
- package/dist/modules/providers/ApiKeyController.js +98 -0
- package/dist/modules/providers/ApiKeyController.js.map +1 -0
- package/dist/modules/providers/PersonalSubscriptionController.d.ts +4 -0
- package/dist/modules/providers/PersonalSubscriptionController.d.ts.map +1 -0
- package/dist/modules/providers/PersonalSubscriptionController.js +48 -0
- package/dist/modules/providers/PersonalSubscriptionController.js.map +1 -0
- package/dist/modules/providers/VendorCredentialController.d.ts +4 -0
- package/dist/modules/providers/VendorCredentialController.d.ts.map +1 -0
- package/dist/modules/providers/VendorCredentialController.js +55 -0
- package/dist/modules/providers/VendorCredentialController.js.map +1 -0
- package/dist/modules/providers/personalCredentialGate.d.ts +34 -0
- package/dist/modules/providers/personalCredentialGate.d.ts.map +1 -0
- package/dist/modules/providers/personalCredentialGate.js +106 -0
- package/dist/modules/providers/personalCredentialGate.js.map +1 -0
- package/dist/modules/recurring/RecurringPipelineController.d.ts +8 -0
- package/dist/modules/recurring/RecurringPipelineController.d.ts.map +1 -0
- package/dist/modules/recurring/RecurringPipelineController.js +58 -0
- package/dist/modules/recurring/RecurringPipelineController.js.map +1 -0
- package/dist/modules/recurring/TrackerSettingsController.d.ts +8 -0
- package/dist/modules/recurring/TrackerSettingsController.d.ts.map +1 -0
- package/dist/modules/recurring/TrackerSettingsController.js +30 -0
- package/dist/modules/recurring/TrackerSettingsController.js.map +1 -0
- package/dist/modules/releaseHealth/ReleaseHealthController.d.ts +9 -0
- package/dist/modules/releaseHealth/ReleaseHealthController.d.ts.map +1 -0
- package/dist/modules/releaseHealth/ReleaseHealthController.js +58 -0
- package/dist/modules/releaseHealth/ReleaseHealthController.js.map +1 -0
- package/dist/modules/requirements/RequirementReviewController.d.ts +12 -0
- package/dist/modules/requirements/RequirementReviewController.d.ts.map +1 -0
- package/dist/modules/requirements/RequirementReviewController.js +107 -0
- package/dist/modules/requirements/RequirementReviewController.js.map +1 -0
- package/dist/modules/runners/RunnerPoolController.d.ts +10 -0
- package/dist/modules/runners/RunnerPoolController.d.ts.map +1 -0
- package/dist/modules/runners/RunnerPoolController.js +52 -0
- package/dist/modules/runners/RunnerPoolController.js.map +1 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.d.ts +9 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.d.ts.map +1 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.js +32 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.js.map +1 -0
- package/dist/modules/services/ServiceMountController.d.ts +11 -0
- package/dist/modules/services/ServiceMountController.d.ts.map +1 -0
- package/dist/modules/services/ServiceMountController.js +64 -0
- package/dist/modules/services/ServiceMountController.js.map +1 -0
- package/dist/modules/settings/WorkspaceSettingsController.d.ts +9 -0
- package/dist/modules/settings/WorkspaceSettingsController.d.ts.map +1 -0
- package/dist/modules/settings/WorkspaceSettingsController.js +32 -0
- package/dist/modules/settings/WorkspaceSettingsController.js.map +1 -0
- package/dist/modules/slack/SlackController.d.ts +17 -0
- package/dist/modules/slack/SlackController.d.ts.map +1 -0
- package/dist/modules/slack/SlackController.js +135 -0
- package/dist/modules/slack/SlackController.js.map +1 -0
- package/dist/modules/tasks/TaskSourceController.d.ts +9 -0
- package/dist/modules/tasks/TaskSourceController.d.ts.map +1 -0
- package/dist/modules/tasks/TaskSourceController.js +103 -0
- package/dist/modules/tasks/TaskSourceController.js.map +1 -0
- package/dist/modules/webSearch/WebSearchProxyController.d.ts +4 -0
- package/dist/modules/webSearch/WebSearchProxyController.d.ts.map +1 -0
- package/dist/modules/webSearch/WebSearchProxyController.js +78 -0
- package/dist/modules/webSearch/WebSearchProxyController.js.map +1 -0
- package/dist/modules/webSearch/upstreams.d.ts +50 -0
- package/dist/modules/webSearch/upstreams.d.ts.map +1 -0
- package/dist/modules/webSearch/upstreams.js +107 -0
- package/dist/modules/webSearch/upstreams.js.map +1 -0
- package/dist/modules/workspaces/WorkspaceController.d.ts +5 -0
- package/dist/modules/workspaces/WorkspaceController.d.ts.map +1 -0
- package/dist/modules/workspaces/WorkspaceController.js +167 -0
- package/dist/modules/workspaces/WorkspaceController.js.map +1 -0
- package/dist/observability/logger.d.ts +9 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +39 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/persistence/mappers.d.ts +101 -0
- package/dist/persistence/mappers.d.ts.map +1 -0
- package/dist/persistence/mappers.js +260 -0
- package/dist/persistence/mappers.js.map +1 -0
- package/dist/runtime/escalateNotifications.d.ts +12 -0
- package/dist/runtime/escalateNotifications.d.ts.map +1 -0
- package/dist/runtime/escalateNotifications.js +25 -0
- package/dist/runtime/escalateNotifications.js.map +1 -0
- package/dist/runtime/gateways.d.ts +159 -0
- package/dist/runtime/gateways.d.ts.map +1 -0
- package/dist/runtime/gateways.js +2 -0
- package/dist/runtime/gateways.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import type { AgentRouting } from '@cat-factory/agents';
|
|
2
|
+
import type { ModelOption } from '@cat-factory/contracts';
|
|
3
|
+
import type { DocumentSourceKind, ModelRef, TaskSourceKind } from '@cat-factory/kernel';
|
|
4
|
+
import type { SpendPricing } from '@cat-factory/spend';
|
|
5
|
+
export interface AgentsConfig {
|
|
6
|
+
routing: AgentRouting;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a block's selected model id to a concrete ref, honouring the
|
|
9
|
+
* direct/Cloudflare fallback based on which provider keys are configured.
|
|
10
|
+
*/
|
|
11
|
+
resolveBlockModel: (modelId: string | undefined) => ModelRef | undefined;
|
|
12
|
+
}
|
|
13
|
+
export interface ExecutionConfig {
|
|
14
|
+
/** Human-decision park timeout passed to the workflow's waitForEvent. */
|
|
15
|
+
decisionTimeout: string;
|
|
16
|
+
/** How long the durable driver sleeps between polls of an async container job. */
|
|
17
|
+
jobPollInterval: string;
|
|
18
|
+
/** Safety bound on the number of polls before a long-running job is failed. */
|
|
19
|
+
jobMaxPolls: number;
|
|
20
|
+
/** How many consecutive status-read failures are tolerated before giving up a job. */
|
|
21
|
+
jobPollFailureTolerance: number;
|
|
22
|
+
/** How long the durable driver sleeps between polls of a `ci` step's CI status. */
|
|
23
|
+
ciPollInterval: string;
|
|
24
|
+
/** Safety bound on the number of CI polls before the gate is given up. */
|
|
25
|
+
ciMaxPolls: number;
|
|
26
|
+
/** Age ceiling for the instance-level container reaper (epoch-ms). */
|
|
27
|
+
containerMaxAgeMs: number;
|
|
28
|
+
}
|
|
29
|
+
export interface PrivilegedAppConfig {
|
|
30
|
+
appId: string;
|
|
31
|
+
}
|
|
32
|
+
export interface GitHubConfig {
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
appId: string;
|
|
35
|
+
appSlug: string;
|
|
36
|
+
apiBase: string;
|
|
37
|
+
/** Browser redirect target after a successful connect (falls back to '/'). */
|
|
38
|
+
setupRedirectUrl: string;
|
|
39
|
+
/** HMAC secret for signing the install `state` (and verifying webhooks); '' when unset. */
|
|
40
|
+
webhookSecret: string;
|
|
41
|
+
/** Present only when a privileged App is configured AND its key is supplied. */
|
|
42
|
+
privilegedApp?: PrivilegedAppConfig;
|
|
43
|
+
}
|
|
44
|
+
/** Google OAuth credentials + (optional) endpoint overrides for "Login with Google". */
|
|
45
|
+
export interface GoogleOAuthConfig {
|
|
46
|
+
clientId: string;
|
|
47
|
+
clientSecret: string;
|
|
48
|
+
/** Explicit redirect_uri; '' means derive `${origin}/auth/google/callback`. */
|
|
49
|
+
redirectUrl: string;
|
|
50
|
+
/** OAuth host (authorize/token); defaults to Google's. */
|
|
51
|
+
oauthBase?: string;
|
|
52
|
+
/** Userinfo API base; defaults to Google's. */
|
|
53
|
+
apiBase?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface AuthConfig {
|
|
56
|
+
/** True when ANY login provider (GitHub OAuth / password / Google) is configured. */
|
|
57
|
+
enabled: boolean;
|
|
58
|
+
/** Local-dev/test ONLY: permit running with auth unconfigured (open API). */
|
|
59
|
+
devOpen: boolean;
|
|
60
|
+
/** GitHub OAuth is offered only when a client id/secret are set. */
|
|
61
|
+
githubEnabled: boolean;
|
|
62
|
+
clientId: string;
|
|
63
|
+
clientSecret: string;
|
|
64
|
+
sessionSecret: string;
|
|
65
|
+
/** REST API base for reading the user (shared with the GitHub integration). */
|
|
66
|
+
apiBase: string;
|
|
67
|
+
/** OAuth host (authorize/token endpoints). */
|
|
68
|
+
oauthBase: string;
|
|
69
|
+
/** Session token lifetime in milliseconds. */
|
|
70
|
+
sessionTtlMs: number;
|
|
71
|
+
/** Fixed post-login landing URL; '' means honour the request-provided one. */
|
|
72
|
+
successRedirectUrl: string;
|
|
73
|
+
/** Explicit OAuth redirect_uri; '' means derive it from the request origin. */
|
|
74
|
+
callbackUrl: string;
|
|
75
|
+
/** Lowercased GitHub logins permitted to sign in (OR with allowedOrgs). */
|
|
76
|
+
allowedLogins: string[];
|
|
77
|
+
/** Lowercased GitHub org logins whose members may sign in (OR with allowedLogins). */
|
|
78
|
+
allowedOrgs: string[];
|
|
79
|
+
/** Extra origins the post-login `redirect` query may target, beyond the request origin. */
|
|
80
|
+
allowedRedirectOrigins: string[];
|
|
81
|
+
/** Whether email/password signup + login is offered. */
|
|
82
|
+
passwordEnabled: boolean;
|
|
83
|
+
/** Google OAuth config, present only when configured. */
|
|
84
|
+
google?: GoogleOAuthConfig;
|
|
85
|
+
/**
|
|
86
|
+
* Lowercased email domains permitted to self-signup (password/Google) without an
|
|
87
|
+
* invite. Empty ⇒ new-user creation is invite-only (the default, fail-closed).
|
|
88
|
+
*/
|
|
89
|
+
allowedEmailDomains: string[];
|
|
90
|
+
}
|
|
91
|
+
export interface EmailConfig {
|
|
92
|
+
/**
|
|
93
|
+
* Opt-in flag. Requires an encryption key (the per-account provider API key is
|
|
94
|
+
* sealed at rest, no plaintext fallback). When false the email module isn't
|
|
95
|
+
* assembled and invitations return a shareable link instead of sending mail.
|
|
96
|
+
* The provider + API key + From address are onboarded per-account in the UI and
|
|
97
|
+
* stored in the DB — NOT read from env — so each org brings its own sender.
|
|
98
|
+
*/
|
|
99
|
+
enabled: boolean;
|
|
100
|
+
/** Service-level master key (base64) backing provider-API-key encryption at rest. */
|
|
101
|
+
encryptionKey?: string;
|
|
102
|
+
/** Public base URL the invite-accept link points at (the SPA origin). */
|
|
103
|
+
appBaseUrl: string;
|
|
104
|
+
}
|
|
105
|
+
export interface DocumentsConfig {
|
|
106
|
+
/**
|
|
107
|
+
* Always on where the runtime serves documents: there is no enable flag, and an
|
|
108
|
+
* encryption key is mandatory (config load fails loudly without it). False only on
|
|
109
|
+
* facades that do not serve documents at all (e.g. the Node MVP).
|
|
110
|
+
*/
|
|
111
|
+
enabled: boolean;
|
|
112
|
+
/** Which source providers to register (default: all). */
|
|
113
|
+
sources: DocumentSourceKind[];
|
|
114
|
+
/** 'llm' uses the agent model to plan structure; 'headings' forces the parser. */
|
|
115
|
+
planner: 'llm' | 'headings';
|
|
116
|
+
/** Service-level master key (base64) backing source-credential encryption at rest. */
|
|
117
|
+
encryptionKey?: string;
|
|
118
|
+
}
|
|
119
|
+
export interface TasksConfig {
|
|
120
|
+
/**
|
|
121
|
+
* Always on where the runtime serves task sources: there is no enable flag, and an
|
|
122
|
+
* encryption key is mandatory (config load fails loudly without it).
|
|
123
|
+
*/
|
|
124
|
+
enabled: boolean;
|
|
125
|
+
/** Which source providers to register (default: all). */
|
|
126
|
+
sources: TaskSourceKind[];
|
|
127
|
+
/** Service-level master key (base64) backing source-credential encryption at rest. */
|
|
128
|
+
encryptionKey?: string;
|
|
129
|
+
}
|
|
130
|
+
export interface EnvironmentsConfig {
|
|
131
|
+
/** Opt-in flag. Requires an encryption key (no silent plaintext fallback). */
|
|
132
|
+
enabled: boolean;
|
|
133
|
+
/** Service-level master key (base64) backing credential encryption at rest. */
|
|
134
|
+
encryptionKey?: string;
|
|
135
|
+
/**
|
|
136
|
+
* Hostnames exempt from the strict public-https URL guard, for a TRUSTED in-house
|
|
137
|
+
* adapter pointing at an internal env platform on a private/VPN host. Each entry
|
|
138
|
+
* matches the URL hostname exactly, or as a dot suffix when it starts with `.`
|
|
139
|
+
* (`.internal`). Absent/empty => strict (no exemptions). Folds into the shared
|
|
140
|
+
* {@link UrlSafetyPolicy} via `resolveUrlSafetyPolicy`.
|
|
141
|
+
*/
|
|
142
|
+
allowUrlHosts?: string[];
|
|
143
|
+
/** Permit `http` (not just `https`) for trusted provider/env URLs. */
|
|
144
|
+
allowHttpUrls?: boolean;
|
|
145
|
+
}
|
|
146
|
+
export interface RunnerPoolConfig {
|
|
147
|
+
/** Opt-in flag. Requires an encryption key (no silent plaintext fallback). */
|
|
148
|
+
enabled: boolean;
|
|
149
|
+
/** Service-level master key (base64) backing credential encryption at rest. */
|
|
150
|
+
encryptionKey?: string;
|
|
151
|
+
/** Hostnames exempt from the strict public-https URL guard (see EnvironmentsConfig). */
|
|
152
|
+
allowUrlHosts?: string[];
|
|
153
|
+
/** Permit `http` (not just `https`) for a trusted internal pool scheduler URL. */
|
|
154
|
+
allowHttpUrls?: boolean;
|
|
155
|
+
}
|
|
156
|
+
export interface DatadogConfig {
|
|
157
|
+
/**
|
|
158
|
+
* Opt-in flag (`DATADOG_ENABLED=true`). Requires an encryption key (the per-workspace
|
|
159
|
+
* API/app keys are sealed at rest, no silent plaintext fallback). When false the
|
|
160
|
+
* post-release-health gate is a pass-through and no release-health module is assembled.
|
|
161
|
+
*/
|
|
162
|
+
enabled: boolean;
|
|
163
|
+
/** Service-level master key (base64) backing Datadog-credential encryption at rest. */
|
|
164
|
+
encryptionKey?: string;
|
|
165
|
+
}
|
|
166
|
+
export interface IncidentEnrichmentConfig {
|
|
167
|
+
/**
|
|
168
|
+
* PagerDuty incident-enrichment, present only when configured. Annotates (never
|
|
169
|
+
* re-alerts) an incident PagerDuty already opened with the on-call investigation.
|
|
170
|
+
*/
|
|
171
|
+
pagerDuty?: {
|
|
172
|
+
apiToken: string;
|
|
173
|
+
fromEmail: string;
|
|
174
|
+
};
|
|
175
|
+
/** incident.io incident-enrichment, present only when configured. */
|
|
176
|
+
incidentIo?: {
|
|
177
|
+
apiKey: string;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
export interface SlackConfig {
|
|
181
|
+
/**
|
|
182
|
+
* Opt-in flag. Requires an encryption key (the per-account bot token is sealed
|
|
183
|
+
* at rest, no silent plaintext fallback). When false the Slack module isn't
|
|
184
|
+
* assembled and no Slack channel is composed into the notification fan-out.
|
|
185
|
+
*/
|
|
186
|
+
enabled: boolean;
|
|
187
|
+
/** Service-level master key (base64) backing bot-token encryption at rest. */
|
|
188
|
+
encryptionKey?: string;
|
|
189
|
+
/**
|
|
190
|
+
* Slack app OAuth credentials, present only when a Slack app was registered.
|
|
191
|
+
* Absent → manual bot-token onboarding still works; OAuth routes aren't offered.
|
|
192
|
+
*/
|
|
193
|
+
oauth?: {
|
|
194
|
+
clientId: string;
|
|
195
|
+
clientSecret: string;
|
|
196
|
+
redirectUrl: string;
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
export interface RetentionConfig {
|
|
200
|
+
tokenUsageMs: number;
|
|
201
|
+
rateLimitMs: number;
|
|
202
|
+
commitMs: number;
|
|
203
|
+
/**
|
|
204
|
+
* LLM observability sink (full per-call prompt/response). Heavy, and only useful
|
|
205
|
+
* for recent debugging, so it is pruned aggressively (default 3 days).
|
|
206
|
+
*/
|
|
207
|
+
llmCallMetricsMs: number;
|
|
208
|
+
}
|
|
209
|
+
export interface FragmentLibraryConfig {
|
|
210
|
+
/** Opt-in flag (`PROMPT_LIBRARY_ENABLED=true`); needs no encryption key. */
|
|
211
|
+
enabled: boolean;
|
|
212
|
+
/** Relevance selection mode: 'llm' ranks per run; 'deterministic' matches tags. */
|
|
213
|
+
selector: 'llm' | 'deterministic';
|
|
214
|
+
}
|
|
215
|
+
export interface ObservabilityConfig {
|
|
216
|
+
/**
|
|
217
|
+
* Whether the LLM observability sink persists the full prompt body with each
|
|
218
|
+
* metric. Default true. When false (`LLM_RECORD_PROMPTS=false`) the numeric
|
|
219
|
+
* telemetry (tokens, timing, finish reason, message/tool counts) is still recorded,
|
|
220
|
+
* but the prompt text is stored empty — for deployments that must not retain the
|
|
221
|
+
* (potentially sensitive) complete prompts sent to the model.
|
|
222
|
+
*/
|
|
223
|
+
recordPrompts: boolean;
|
|
224
|
+
}
|
|
225
|
+
export interface LangfuseConfig {
|
|
226
|
+
/**
|
|
227
|
+
* Opt-in flag (`LANGFUSE_ENABLED=true`). Requires both keys; when false (or a key is
|
|
228
|
+
* missing) no Langfuse sink is built and there is no external emission. Off by default,
|
|
229
|
+
* exactly like every other opt-in integration (Slack, environments, runners).
|
|
230
|
+
*/
|
|
231
|
+
enabled: boolean;
|
|
232
|
+
/** Langfuse public key (`pk-lf-…`). */
|
|
233
|
+
publicKey?: string;
|
|
234
|
+
/** Langfuse secret key (`sk-lf-…`). */
|
|
235
|
+
secretKey?: string;
|
|
236
|
+
/** Host of the Langfuse instance; defaults to Langfuse Cloud when omitted. */
|
|
237
|
+
baseUrl?: string;
|
|
238
|
+
}
|
|
239
|
+
export interface LocalModeConfig {
|
|
240
|
+
/**
|
|
241
|
+
* True on the local-mode facade (a single developer running the whole product on
|
|
242
|
+
* their own machine). Absent/false on the Worker and stock Node facades.
|
|
243
|
+
*/
|
|
244
|
+
enabled: boolean;
|
|
245
|
+
/**
|
|
246
|
+
* When local mode is running WITHOUT a GitHub PAT, a github.com URL with the scopes
|
|
247
|
+
* local mode needs pre-selected, so the developer can create one in a single click.
|
|
248
|
+
* Absent once a PAT is configured. The SPA surfaces this as a dismissible banner so
|
|
249
|
+
* the warning isn't lost in the server console.
|
|
250
|
+
*/
|
|
251
|
+
githubPatSetupUrl?: string;
|
|
252
|
+
}
|
|
253
|
+
export interface AppConfig {
|
|
254
|
+
agents: AgentsConfig;
|
|
255
|
+
/** The effective model picker catalog (each model's active flavour). */
|
|
256
|
+
models: ModelOption[];
|
|
257
|
+
execution: ExecutionConfig;
|
|
258
|
+
/** Pricing + budget for the spend safeguard. */
|
|
259
|
+
spend: SpendPricing;
|
|
260
|
+
/** GitHub integration config; `enabled` is false unless a GitHub App is set up. */
|
|
261
|
+
github: GitHubConfig;
|
|
262
|
+
/** "Login with GitHub" config; `enabled` is false unless an OAuth app is set up. */
|
|
263
|
+
auth: AuthConfig;
|
|
264
|
+
/** Document-source integration config; always on where the runtime serves documents. */
|
|
265
|
+
documents: DocumentsConfig;
|
|
266
|
+
/** Task-source integration config; always on where the runtime serves task sources. */
|
|
267
|
+
tasks: TasksConfig;
|
|
268
|
+
/** Environment provider integration config; `enabled` is false unless opted in. */
|
|
269
|
+
environments: EnvironmentsConfig;
|
|
270
|
+
/** Self-hosted runner-pool config; `enabled` is false unless opted in. */
|
|
271
|
+
runners: RunnerPoolConfig;
|
|
272
|
+
/** Slack notification-transport config; `enabled` is false unless opted in. */
|
|
273
|
+
slack: SlackConfig;
|
|
274
|
+
/** Datadog post-release-health config; `enabled` is false unless opted in. */
|
|
275
|
+
datadog: DatadogConfig;
|
|
276
|
+
/** Optional PagerDuty / incident.io incident-enrichment config (additive, opt-in). */
|
|
277
|
+
incidentEnrichment: IncidentEnrichmentConfig;
|
|
278
|
+
/** Transactional email config (invitations); `enabled` is false unless opted in. */
|
|
279
|
+
email: EmailConfig;
|
|
280
|
+
/** Retention windows for the unbounded ledgers/projections (epoch-ms ages). */
|
|
281
|
+
retention: RetentionConfig;
|
|
282
|
+
/** Prompt-fragment library config; `enabled` is false unless opted in (ADR 0006). */
|
|
283
|
+
fragmentLibrary: FragmentLibraryConfig;
|
|
284
|
+
/** LLM observability config (e.g. whether complete prompts are recorded). */
|
|
285
|
+
observability: ObservabilityConfig;
|
|
286
|
+
/** Optional Langfuse trace-sink config; `enabled` is false unless opted in. */
|
|
287
|
+
langfuse: LangfuseConfig;
|
|
288
|
+
/**
|
|
289
|
+
* Local-mode facade signals surfaced to the SPA; present only on the local facade
|
|
290
|
+
* (the Worker/Node facades leave it undefined). Carries the missing-PAT setup prompt.
|
|
291
|
+
*/
|
|
292
|
+
localMode?: LocalModeConfig;
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { UrlSafetyPolicy } from '@cat-factory/kernel';
|
|
2
|
+
/** The per-integration config fields that widen the strict URL/host guard. */
|
|
3
|
+
export interface UrlSafetyConfigSlice {
|
|
4
|
+
allowUrlHosts?: string[];
|
|
5
|
+
allowHttpUrls?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function resolveUrlSafetyPolicy(slice: UrlSafetyConfigSlice): UrlSafetyPolicy | undefined;
|
|
8
|
+
//# sourceMappingURL=url-safety.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-safety.d.ts","sourceRoot":"","sources":["../../src/config/url-safety.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAU1D,8EAA8E;AAC9E,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,oBAAoB,GAAG,eAAe,GAAG,SAAS,CAQ/F"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function resolveUrlSafetyPolicy(slice) {
|
|
2
|
+
const hosts = [...new Set((slice.allowUrlHosts ?? []).map((h) => h.trim()).filter(Boolean))];
|
|
3
|
+
const allowHttp = Boolean(slice.allowHttpUrls);
|
|
4
|
+
if (hosts.length === 0 && !allowHttp)
|
|
5
|
+
return undefined;
|
|
6
|
+
return {
|
|
7
|
+
schemes: allowHttp ? ['https', 'http'] : ['https'],
|
|
8
|
+
allowHosts: hosts,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=url-safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-safety.js","sourceRoot":"","sources":["../../src/config/url-safety.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,sBAAsB,CAAC,KAA2B;IAChE,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAC5F,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;IAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS;QAAE,OAAO,SAAS,CAAA;IACtD,OAAO;QACL,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAClD,UAAU,EAAE,KAAK;KAClB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { TOKEN_AUDIENCE } from '../auth/signing.js';
|
|
2
|
+
/** Claims carried by a container session token. */
|
|
3
|
+
export interface ContainerSession {
|
|
4
|
+
/** Audience pin — always `llm-proxy`; rejected by the user-session verifier. */
|
|
5
|
+
aud: typeof TOKEN_AUDIENCE.container;
|
|
6
|
+
/** Workspace the run belongs to (spend is metered against it). */
|
|
7
|
+
workspaceId: string;
|
|
8
|
+
/**
|
|
9
|
+
* The workspace's owning account id, so the proxy can lease an account-scoped API
|
|
10
|
+
* key from the merged pool. Absent for a legacy/unscoped workspace.
|
|
11
|
+
*/
|
|
12
|
+
accountId?: string;
|
|
13
|
+
/**
|
|
14
|
+
* The run initiator's `usr_*` id, so the proxy can also lease the initiator's own
|
|
15
|
+
* user-scoped API keys. Absent for system-initiated runs.
|
|
16
|
+
*/
|
|
17
|
+
userId?: string;
|
|
18
|
+
/** Execution instance id (links proxied usage to the run). */
|
|
19
|
+
executionId: string;
|
|
20
|
+
/** Agent kind performing the work, for the spend ledger. */
|
|
21
|
+
agentKind: string;
|
|
22
|
+
/** Locked upstream provider id (e.g. `qwen`, `deepseek`, `moonshot`). */
|
|
23
|
+
provider: string;
|
|
24
|
+
/** Locked upstream model id (e.g. `qwen3-max`). */
|
|
25
|
+
model: string;
|
|
26
|
+
/** Absolute expiry, epoch ms. */
|
|
27
|
+
exp: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Default session lifetime. Must clear the harness job watchdog ceiling
|
|
31
|
+
* (`JOB_MAX_DURATION_MS`, default 60 min) PLUS the dispatch→container-boot lead
|
|
32
|
+
* (the token is minted at dispatch, before Pi starts), or a long but healthy step
|
|
33
|
+
* 401s mid-run once the token expires while the watchdog still considers it alive.
|
|
34
|
+
* 90 min = 60 min job + ~10 min boot lead + margin. The token is tightly scoped
|
|
35
|
+
* (audience `llm-proxy`, one workspace, one execution, locked provider+model), so a
|
|
36
|
+
* longer life is a small risk increase: a leak can only spend that run's metered
|
|
37
|
+
* budget on that one model. If you raise `JOB_MAX_DURATION_MS`, raise this too.
|
|
38
|
+
*/
|
|
39
|
+
export declare const DEFAULT_SESSION_TTL_MS: number;
|
|
40
|
+
export interface MintInput {
|
|
41
|
+
workspaceId: string;
|
|
42
|
+
accountId?: string | null;
|
|
43
|
+
userId?: string | null;
|
|
44
|
+
executionId: string;
|
|
45
|
+
agentKind: string;
|
|
46
|
+
provider: string;
|
|
47
|
+
model: string;
|
|
48
|
+
/** Override the default TTL (ms). */
|
|
49
|
+
ttlMs?: number;
|
|
50
|
+
}
|
|
51
|
+
export declare class ContainerSessionService {
|
|
52
|
+
private readonly signer;
|
|
53
|
+
private readonly now;
|
|
54
|
+
constructor({ secret, now }: {
|
|
55
|
+
secret: string;
|
|
56
|
+
now?: () => number;
|
|
57
|
+
});
|
|
58
|
+
/** Mint a signed token for one run. */
|
|
59
|
+
mint(input: MintInput): Promise<string>;
|
|
60
|
+
/**
|
|
61
|
+
* Verify a bearer token, returning its claims or null when invalid/expired.
|
|
62
|
+
* Pins the `llm-proxy` audience so a user session token (same secret) cannot
|
|
63
|
+
* be used to drive the proxy, and vice-versa.
|
|
64
|
+
*/
|
|
65
|
+
verify(token: string | null | undefined): Promise<ContainerSession | null>;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=ContainerSessionService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContainerSessionService.d.ts","sourceRoot":"","sources":["../../src/containers/ContainerSessionService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAS/D,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAC/B,gFAAgF;IAChF,GAAG,EAAE,OAAO,cAAc,CAAC,SAAS,CAAA;IACpC,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAA;IACnB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAA;IAChB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAA;IACb,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAA;CACZ;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,QAAiB,CAAA;AAEpD,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;IAElC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;KAAE,EAGlE;IAED,uCAAuC;IACvC,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAatC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAEzE;CACF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { HmacSigner, TOKEN_AUDIENCE } from '../auth/signing.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default session lifetime. Must clear the harness job watchdog ceiling
|
|
4
|
+
* (`JOB_MAX_DURATION_MS`, default 60 min) PLUS the dispatch→container-boot lead
|
|
5
|
+
* (the token is minted at dispatch, before Pi starts), or a long but healthy step
|
|
6
|
+
* 401s mid-run once the token expires while the watchdog still considers it alive.
|
|
7
|
+
* 90 min = 60 min job + ~10 min boot lead + margin. The token is tightly scoped
|
|
8
|
+
* (audience `llm-proxy`, one workspace, one execution, locked provider+model), so a
|
|
9
|
+
* longer life is a small risk increase: a leak can only spend that run's metered
|
|
10
|
+
* budget on that one model. If you raise `JOB_MAX_DURATION_MS`, raise this too.
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_SESSION_TTL_MS = 90 * 60 * 1000;
|
|
13
|
+
export class ContainerSessionService {
|
|
14
|
+
signer;
|
|
15
|
+
now;
|
|
16
|
+
constructor({ secret, now }) {
|
|
17
|
+
this.signer = new HmacSigner(secret);
|
|
18
|
+
this.now = now ?? (() => Date.now());
|
|
19
|
+
}
|
|
20
|
+
/** Mint a signed token for one run. */
|
|
21
|
+
mint(input) {
|
|
22
|
+
const session = {
|
|
23
|
+
aud: TOKEN_AUDIENCE.container,
|
|
24
|
+
workspaceId: input.workspaceId,
|
|
25
|
+
...(input.accountId ? { accountId: input.accountId } : {}),
|
|
26
|
+
...(input.userId ? { userId: input.userId } : {}),
|
|
27
|
+
executionId: input.executionId,
|
|
28
|
+
agentKind: input.agentKind,
|
|
29
|
+
provider: input.provider,
|
|
30
|
+
model: input.model,
|
|
31
|
+
exp: this.now() + (input.ttlMs ?? DEFAULT_SESSION_TTL_MS),
|
|
32
|
+
};
|
|
33
|
+
return this.signer.sign(session);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Verify a bearer token, returning its claims or null when invalid/expired.
|
|
37
|
+
* Pins the `llm-proxy` audience so a user session token (same secret) cannot
|
|
38
|
+
* be used to drive the proxy, and vice-versa.
|
|
39
|
+
*/
|
|
40
|
+
verify(token) {
|
|
41
|
+
return this.signer.verify(token, { aud: TOKEN_AUDIENCE.container });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=ContainerSessionService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContainerSessionService.js","sourceRoot":"","sources":["../../src/containers/ContainerSessionService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAqC/D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAcpD,MAAM,OAAO,uBAAuB;IACjB,MAAM,CAAY;IAClB,GAAG,CAAc;IAElC,YAAY,EAAE,MAAM,EAAE,GAAG,EAA0C;QACjE,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAA;QACpC,IAAI,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;IACtC,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC,KAAgB;QACnB,MAAM,OAAO,GAAqB;YAChC,GAAG,EAAE,cAAc,CAAC,SAAS;YAC7B,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,sBAAsB,CAAC;SAC1D,CAAA;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAClC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAgC;QACrC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAmB,KAAK,EAAE,EAAE,GAAG,EAAE,cAAc,CAAC,SAAS,EAAE,CAAC,CAAA;IACvF,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PasswordHasher } from '@cat-factory/kernel';
|
|
2
|
+
export declare class WebCryptoPasswordHasher implements PasswordHasher {
|
|
3
|
+
private readonly iterations;
|
|
4
|
+
constructor(iterations?: number);
|
|
5
|
+
hash(password: string): Promise<string>;
|
|
6
|
+
verify(password: string, stored: string): Promise<boolean>;
|
|
7
|
+
needsRehash(stored: string): boolean;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=WebCryptoPasswordHasher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebCryptoPasswordHasher.d.ts","sourceRoot":"","sources":["../../src/crypto/WebCryptoPasswordHasher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAqBzD,qBAAa,uBAAwB,YAAW,cAAc;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU;IAAvC,YAA6B,UAAU,GAAE,MAA2B,EAAI;IAElE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI5C;IAEK,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAK/D;IAED,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAInC;CACF"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { base64url, base64urlToBytes, timingSafeEqual } from './encoding.js';
|
|
2
|
+
// Password hashing for the email/password login provider, built on Web Crypto
|
|
3
|
+
// (PBKDF2-HMAC-SHA256) so it runs identically on Cloudflare workerd and Node —
|
|
4
|
+
// native argon2/bcrypt modules do NOT load in a Workers isolate, which would split
|
|
5
|
+
// the runtimes. A random per-record salt + a high iteration count are embedded in a
|
|
6
|
+
// self-describing PHC-like string so `verify` re-derives without external params:
|
|
7
|
+
//
|
|
8
|
+
// pbkdf2-sha256$i=<iterations>$<base64url(salt)>$<base64url(hash)>
|
|
9
|
+
//
|
|
10
|
+
// `verify` is constant-time (timingSafeEqual) and fails closed on any malformed
|
|
11
|
+
// stored value.
|
|
12
|
+
// OWASP-recommended floor for PBKDF2-HMAC-SHA256 (2023). Paid once per login, not
|
|
13
|
+
// per request.
|
|
14
|
+
const DEFAULT_ITERATIONS = 210_000;
|
|
15
|
+
const SALT_BYTES = 16;
|
|
16
|
+
const HASH_BYTES = 32;
|
|
17
|
+
const SCHEME = 'pbkdf2-sha256';
|
|
18
|
+
export class WebCryptoPasswordHasher {
|
|
19
|
+
iterations;
|
|
20
|
+
constructor(iterations = DEFAULT_ITERATIONS) {
|
|
21
|
+
this.iterations = iterations;
|
|
22
|
+
}
|
|
23
|
+
async hash(password) {
|
|
24
|
+
const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES));
|
|
25
|
+
const derived = await deriveBits(password, salt, this.iterations);
|
|
26
|
+
return `${SCHEME}$i=${this.iterations}$${base64url(salt)}$${base64url(derived)}`;
|
|
27
|
+
}
|
|
28
|
+
async verify(password, stored) {
|
|
29
|
+
const parsed = parseStored(stored);
|
|
30
|
+
if (!parsed)
|
|
31
|
+
return false;
|
|
32
|
+
const derived = new Uint8Array(await deriveBits(password, parsed.salt, parsed.iterations));
|
|
33
|
+
return timingSafeEqual(derived, parsed.expected);
|
|
34
|
+
}
|
|
35
|
+
needsRehash(stored) {
|
|
36
|
+
const parsed = parseStored(stored);
|
|
37
|
+
// Unparseable ⇒ upgrade it; otherwise upgrade anything below the current cost.
|
|
38
|
+
return !parsed || parsed.iterations < this.iterations;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Parse a stored PHC-like value, or null on any malformed input (fail closed). */
|
|
42
|
+
function parseStored(stored) {
|
|
43
|
+
const parts = stored.split('$');
|
|
44
|
+
if (parts.length !== 4 || parts[0] !== SCHEME)
|
|
45
|
+
return null;
|
|
46
|
+
const iterMatch = /^i=(\d+)$/.exec(parts[1]);
|
|
47
|
+
if (!iterMatch)
|
|
48
|
+
return null;
|
|
49
|
+
const iterations = Number(iterMatch[1]);
|
|
50
|
+
if (!Number.isInteger(iterations) || iterations < 1)
|
|
51
|
+
return null;
|
|
52
|
+
try {
|
|
53
|
+
return {
|
|
54
|
+
iterations,
|
|
55
|
+
salt: base64urlToBytes(parts[2]),
|
|
56
|
+
expected: base64urlToBytes(parts[3]),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function deriveBits(password, salt, iterations) {
|
|
64
|
+
const baseKey = await crypto.subtle.importKey('raw', new TextEncoder().encode(password), 'PBKDF2', false, ['deriveBits']);
|
|
65
|
+
return crypto.subtle.deriveBits({ name: 'PBKDF2', hash: 'SHA-256', salt: salt, iterations }, baseKey, HASH_BYTES * 8);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=WebCryptoPasswordHasher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebCryptoPasswordHasher.js","sourceRoot":"","sources":["../../src/crypto/WebCryptoPasswordHasher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PersonalSecretCipher } from '@cat-factory/kernel';
|
|
2
|
+
export declare class WebCryptoPersonalSecretCipher implements PersonalSecretCipher {
|
|
3
|
+
seal(plaintext: string, password: string): Promise<string>;
|
|
4
|
+
open(envelope: string, password: string): Promise<string>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=WebCryptoPersonalSecretCipher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebCryptoPersonalSecretCipher.d.ts","sourceRoot":"","sources":["../../src/crypto/WebCryptoPersonalSecretCipher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAyB/D,qBAAa,6BAA8B,YAAW,oBAAoB;IAClE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAU/D;IAEK,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB9D;CACF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { base64url, base64urlToBytes } from './encoding.js';
|
|
2
|
+
// The SECOND, password-derived encryption layer for individual-usage subscriptions
|
|
3
|
+
// (see the PersonalSecretCipher port). A key is derived from the user's personal
|
|
4
|
+
// password via PBKDF2-HMAC-SHA256 (random per-record salt) and used for AES-256-GCM.
|
|
5
|
+
// No master key is involved — only the password the user types — so the resulting
|
|
6
|
+
// envelope is undecryptable without it. The system SecretCipher is layered on top of
|
|
7
|
+
// this envelope at rest, so recovering a credential needs BOTH the system key AND the
|
|
8
|
+
// user's password.
|
|
9
|
+
//
|
|
10
|
+
// envelope = "pv1." + base64url(salt) + "." + base64url(iv) + "." + base64url(MAGIC|plaintext sealed)
|
|
11
|
+
//
|
|
12
|
+
// A fixed MAGIC prefix is sealed with the plaintext so a wrong password is detected
|
|
13
|
+
// deterministically (in addition to the GCM auth tag), surfaced to the caller as a
|
|
14
|
+
// thrown error which the service maps to a `wrong_password` credential error.
|
|
15
|
+
const VERSION = 'pv1';
|
|
16
|
+
const SALT_BYTES = 16;
|
|
17
|
+
const IV_BYTES = 12;
|
|
18
|
+
// OWASP-recommended floor for PBKDF2-HMAC-SHA256 (2023). Runs once per unlock, not per
|
|
19
|
+
// step, so the cost is paid at task start/retry only.
|
|
20
|
+
const PBKDF2_ITERATIONS = 210_000;
|
|
21
|
+
const MAGIC = 'cfpers1:';
|
|
22
|
+
export class WebCryptoPersonalSecretCipher {
|
|
23
|
+
async seal(plaintext, password) {
|
|
24
|
+
const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES));
|
|
25
|
+
const iv = crypto.getRandomValues(new Uint8Array(IV_BYTES));
|
|
26
|
+
const key = await deriveKey(password, salt);
|
|
27
|
+
const sealed = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, new TextEncoder().encode(MAGIC + plaintext));
|
|
28
|
+
return [VERSION, base64url(salt), base64url(iv), base64url(new Uint8Array(sealed))].join('.');
|
|
29
|
+
}
|
|
30
|
+
async open(envelope, password) {
|
|
31
|
+
const parts = envelope.split('.');
|
|
32
|
+
if (parts.length !== 4 || parts[0] !== VERSION) {
|
|
33
|
+
throw new Error('Invalid personal secret envelope');
|
|
34
|
+
}
|
|
35
|
+
const salt = base64urlToBytes(parts[1]);
|
|
36
|
+
const iv = base64urlToBytes(parts[2]);
|
|
37
|
+
const ciphertext = base64urlToBytes(parts[3]);
|
|
38
|
+
const key = await deriveKey(password, salt);
|
|
39
|
+
// A wrong password fails the GCM auth tag and throws here.
|
|
40
|
+
const plain = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, ciphertext);
|
|
41
|
+
const text = new TextDecoder().decode(plain);
|
|
42
|
+
if (!text.startsWith(MAGIC)) {
|
|
43
|
+
throw new Error('Personal secret failed integrity check');
|
|
44
|
+
}
|
|
45
|
+
return text.slice(MAGIC.length);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function deriveKey(password, salt) {
|
|
49
|
+
const baseKey = await crypto.subtle.importKey('raw', new TextEncoder().encode(password), 'PBKDF2', false, ['deriveKey']);
|
|
50
|
+
return crypto.subtle.deriveKey({
|
|
51
|
+
name: 'PBKDF2',
|
|
52
|
+
hash: 'SHA-256',
|
|
53
|
+
salt: salt,
|
|
54
|
+
iterations: PBKDF2_ITERATIONS,
|
|
55
|
+
}, baseKey, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=WebCryptoPersonalSecretCipher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebCryptoPersonalSecretCipher.js","sourceRoot":"","sources":["../../src/crypto/WebCryptoPersonalSecretCipher.ts"],"names":[],"mappings":"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"}
|