@mastra/factory 0.25.0-alpha.4 → 0.25.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/auth.js +1 -2
- package/dist/boards/define-board.js +1 -2
- package/dist/boards/index.js +1 -2
- package/dist/boards/registry.js +1 -2
- package/dist/boards/relocate.js +1 -2
- package/dist/boards/review.js +1 -2
- package/dist/boards/semantics.js +1 -2
- package/dist/boards/transition-policy.js +1 -2
- package/dist/boards/work-tool-rules.js +1 -2
- package/dist/boards/work-transition-policy.js +1 -2
- package/dist/boards/work.js +1 -2
- package/dist/default-thinking-level.d.ts +3 -0
- package/dist/default-thinking-level.d.ts.map +1 -0
- package/dist/default-thinking-level.js +5 -0
- package/dist/default-thinking-level.js.map +1 -0
- package/dist/environment/build-runner.js +1 -2
- package/dist/environment/build-schedule.js +1 -2
- package/dist/environment/build-workflow.js +1 -2
- package/dist/environment/build.js +1 -2
- package/dist/environment/heads.js +1 -2
- package/dist/factory.d.ts +4 -2
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +62 -21
- package/dist/factory.js.map +1 -1
- package/dist/feed-events.js +1 -2
- package/dist/index.js +2 -2
- package/dist/integrations/channel-thread-announcements.d.ts +8 -0
- package/dist/integrations/channel-thread-announcements.d.ts.map +1 -0
- package/dist/integrations/channel-thread-announcements.js +16 -0
- package/dist/integrations/channel-thread-announcements.js.map +1 -0
- package/dist/integrations/github/acceptance-labels.js +1 -2
- package/dist/integrations/github/app-identity.js +1 -2
- package/dist/integrations/github/commits.js +1 -2
- package/dist/integrations/github/config.js +1 -2
- package/dist/integrations/github/default-rules.js +2 -3
- package/dist/integrations/github/integration.js +3 -4
- package/dist/integrations/github/issue-reconciler.js +1 -2
- package/dist/integrations/github/pat.js +1 -2
- package/dist/integrations/github/provenance.d.ts.map +1 -1
- package/dist/integrations/github/provenance.js +2 -5
- package/dist/integrations/github/provenance.js.map +1 -1
- package/dist/integrations/github/reconcile-worker.js +1 -2
- package/dist/integrations/github/reconciliation-config.js +1 -2
- package/dist/integrations/github/routes.js +4 -5
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +14 -3
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/github/sandbox-release.js +1 -2
- package/dist/integrations/github/sandbox.js +1 -2
- package/dist/integrations/github/session-subscriptions.js +1 -2
- package/dist/integrations/github/settle-or-abort.js +1 -2
- package/dist/integrations/github/stale-reviews.js +1 -2
- package/dist/integrations/github/subscriptions.js +1 -2
- package/dist/integrations/github/token-refresh.js +1 -2
- package/dist/integrations/github/webhook.d.ts.map +1 -1
- package/dist/integrations/github/webhook.js +17 -3
- package/dist/integrations/github/webhook.js.map +1 -1
- package/dist/integrations/gitlab/agent-tools.js +1 -2
- package/dist/integrations/gitlab/api.js +1 -2
- package/dist/integrations/gitlab/default-rules.js +1 -2
- package/dist/integrations/gitlab/integration.d.ts +4 -0
- package/dist/integrations/gitlab/integration.d.ts.map +1 -1
- package/dist/integrations/gitlab/integration.js +12 -4
- package/dist/integrations/gitlab/integration.js.map +1 -1
- package/dist/integrations/gitlab/issue-reconciler.js +1 -2
- package/dist/integrations/gitlab/merge-request-reconciler.js +1 -2
- package/dist/integrations/gitlab/reconciler.js +1 -2
- package/dist/integrations/gitlab/reconciliation-config.js +1 -2
- package/dist/integrations/gitlab/routes.d.ts +6 -0
- package/dist/integrations/gitlab/routes.d.ts.map +1 -1
- package/dist/integrations/gitlab/routes.js +154 -3
- package/dist/integrations/gitlab/routes.js.map +1 -1
- package/dist/integrations/gitlab/rules.d.ts.map +1 -1
- package/dist/integrations/gitlab/rules.js +5 -3
- package/dist/integrations/gitlab/rules.js.map +1 -1
- package/dist/integrations/gitlab/session-subscriptions.js +1 -2
- package/dist/integrations/gitlab/subscriptions.js +1 -2
- package/dist/integrations/gitlab/version-control.js +1 -2
- package/dist/integrations/gitlab/webhook-dispatch.js +1 -2
- package/dist/integrations/gitlab/webhook.js +1 -2
- package/dist/integrations/incidentio/agent-tools.js +1 -2
- package/dist/integrations/incidentio/api.js +1 -2
- package/dist/integrations/incidentio/claim.js +1 -2
- package/dist/integrations/incidentio/default-rules.js +1 -2
- package/dist/integrations/incidentio/intake.js +1 -2
- package/dist/integrations/incidentio/integration.js +1 -2
- package/dist/integrations/incidentio/issue-reconciler.js +1 -2
- package/dist/integrations/incidentio/reconciliation-config.js +1 -2
- package/dist/integrations/incidentio/routes.js +1 -2
- package/dist/integrations/incidentio/rules.js +1 -2
- package/dist/integrations/issue-reconcile-worker.js +1 -2
- package/dist/integrations/issue-reconciler.js +1 -2
- package/dist/integrations/jira/adf.js +1 -2
- package/dist/integrations/jira/agent-tools.js +1 -2
- package/dist/integrations/jira/api.d.ts +1 -1
- package/dist/integrations/jira/api.d.ts.map +1 -1
- package/dist/integrations/jira/api.js +2 -3
- package/dist/integrations/jira/api.js.map +1 -1
- package/dist/integrations/jira/claim.js +1 -2
- package/dist/integrations/jira/default-rules.js +1 -2
- package/dist/integrations/jira/integration.d.ts +3 -1
- package/dist/integrations/jira/integration.d.ts.map +1 -1
- package/dist/integrations/jira/integration.js +18 -4
- package/dist/integrations/jira/integration.js.map +1 -1
- package/dist/integrations/jira/issue-reconciler.js +1 -2
- package/dist/integrations/jira/reconciliation-config.js +1 -2
- package/dist/integrations/jira/routes.js +1 -2
- package/dist/integrations/jira/rules.js +1 -2
- package/dist/integrations/linear/agent-tools.d.ts +1 -1
- package/dist/integrations/linear/agent-tools.d.ts.map +1 -1
- package/dist/integrations/linear/agent-tools.js +5 -5
- package/dist/integrations/linear/agent-tools.js.map +1 -1
- package/dist/integrations/linear/claim.js +1 -2
- package/dist/integrations/linear/default-rules.js +1 -2
- package/dist/integrations/linear/integration.d.ts +2 -0
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/integration.js +2 -2
- package/dist/integrations/linear/integration.js.map +1 -1
- package/dist/integrations/linear/issue-reconciler.js +1 -2
- package/dist/integrations/linear/reconciliation-config.js +1 -2
- package/dist/integrations/linear/routes.js +1 -2
- package/dist/integrations/linear/rules.js +1 -2
- package/dist/integrations/platform/api-client.js +1 -2
- package/dist/integrations/platform/connect/routes.js +1 -2
- package/dist/integrations/platform/github/event-worker.js +6 -2
- package/dist/integrations/platform/github/event-worker.js.map +1 -1
- package/dist/integrations/platform/github/integration.js +1 -2
- package/dist/integrations/platform/gitlab/event-worker.js +1 -2
- package/dist/integrations/platform/gitlab/integration.js +1 -2
- package/dist/integrations/platform/incidentio/integration.js +1 -2
- package/dist/integrations/platform/jira/agent-tools.js +1 -2
- package/dist/integrations/platform/jira/integration.js +1 -2
- package/dist/integrations/platform/jira/routes.js +1 -2
- package/dist/integrations/platform/linear/event-worker.js +1 -2
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.js +2 -2
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/integrations/pull-request-head.d.ts +1 -0
- package/dist/integrations/pull-request-head.d.ts.map +1 -1
- package/dist/integrations/pull-request-head.js +3 -3
- package/dist/integrations/pull-request-head.js.map +1 -1
- package/dist/integrations/reconciliation-config.js +1 -2
- package/dist/integrations/slack/channel-reply-processor.d.ts +1 -0
- package/dist/integrations/slack/channel-reply-processor.d.ts.map +1 -1
- package/dist/integrations/slack/channel-reply-processor.js +16 -6
- package/dist/integrations/slack/channel-reply-processor.js.map +1 -1
- package/dist/integrations/slack/channel-session-link-processor.d.ts +1 -0
- package/dist/integrations/slack/channel-session-link-processor.d.ts.map +1 -1
- package/dist/integrations/slack/channel-session-link-processor.js +2 -3
- package/dist/integrations/slack/channel-session-link-processor.js.map +1 -1
- package/dist/integrations/slack/connect-route.js +1 -2
- package/dist/integrations/slack/emoji-shortcodes.generated.js +1 -2
- package/dist/integrations/slack/emoji.js +1 -2
- package/dist/integrations/slack/feed-publisher.js +1 -2
- package/dist/integrations/slack/integration.d.ts +5 -0
- package/dist/integrations/slack/integration.d.ts.map +1 -1
- package/dist/integrations/slack/integration.js +13 -2
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/reply-reminder-processor.js +1 -2
- package/dist/integrations/slack/reply-tool.d.ts.map +1 -1
- package/dist/integrations/slack/reply-tool.js +4 -13
- package/dist/integrations/slack/reply-tool.js.map +1 -1
- package/dist/integrations/slack/run-error-card.d.ts +3 -0
- package/dist/integrations/slack/run-error-card.d.ts.map +1 -0
- package/dist/integrations/slack/run-error-card.js +44 -0
- package/dist/integrations/slack/run-error-card.js.map +1 -0
- package/dist/integrations/slack/share-file-tool.js +1 -2
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +7 -4
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/integrations/subscription-session.js +1 -2
- package/dist/integrations/workos/integration.js +1 -2
- package/dist/mcp/disconnect.js +1 -2
- package/dist/mcp/events.js +2 -3
- package/dist/mcp/routes.js +1 -2
- package/dist/packages/_internals/workspace/dist/index.js +1 -2
- package/dist/packages/_internals/workspace/dist/index.js.map +1 -1
- package/dist/platform-auth-host.js +1 -2
- package/dist/provider-display-name.js +1 -2
- package/dist/review-verdict.d.ts +1 -0
- package/dist/review-verdict.d.ts.map +1 -1
- package/dist/review-verdict.js +9 -3
- package/dist/review-verdict.js.map +1 -1
- package/dist/routes/attention-activity.js +1 -2
- package/dist/routes/attention-parked.js +1 -2
- package/dist/routes/attention-proposed.js +1 -2
- package/dist/routes/attention-providers.js +1 -2
- package/dist/routes/attention.js +1 -2
- package/dist/routes/automation-runs.js +1 -2
- package/dist/routes/config.d.ts +7 -0
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +29 -3
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/contracts.js +1 -2
- package/dist/routes/custom-provider-source.js +1 -2
- package/dist/routes/fs.js +1 -2
- package/dist/routes/intake.js +6 -4
- package/dist/routes/intake.js.map +1 -1
- package/dist/routes/knowledge.js +1 -2
- package/dist/routes/oauth.js +1 -2
- package/dist/routes/projects.js +1 -2
- package/dist/routes/provider-credentials.js +1 -2
- package/dist/routes/route.js +1 -2
- package/dist/routes/session-access.js +1 -2
- package/dist/routes/skills.js +1 -2
- package/dist/routes/source-control-sessions.js +5 -6
- package/dist/routes/source-control-settings.js +1 -2
- package/dist/routes/surface.js +3 -4
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/telemetry.js +1 -2
- package/dist/routes/tenant-credentials.js +1 -2
- package/dist/routes/work-items.js +2 -3
- package/dist/rules/binding-context.js +1 -2
- package/dist/rules/decision-applicability.js +1 -2
- package/dist/rules/dispatch-errors.js +1 -2
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +9 -3
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/event-rules.js +1 -2
- package/dist/rules/processor.js +1 -2
- package/dist/rules/resolve.js +1 -2
- package/dist/rules/review-source-tool.js +1 -2
- package/dist/rules/start-coordinator.js +1 -2
- package/dist/rules/terminal-cleanup.js +1 -2
- package/dist/rules/tools.js +1 -2
- package/dist/rules/transition-service.js +1 -2
- package/dist/rules/types.d.ts +4 -1
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js +1 -2
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.js +1 -2
- package/dist/run-error.d.ts +13 -0
- package/dist/run-error.d.ts.map +1 -0
- package/dist/run-error.js +81 -0
- package/dist/run-error.js.map +1 -0
- package/dist/sandbox/callback-factory-sandbox.js +1 -2
- package/dist/sandbox/git-ref.js +1 -2
- package/dist/sandbox/local-factory-sandbox.d.ts +12 -4
- package/dist/sandbox/local-factory-sandbox.d.ts.map +1 -1
- package/dist/sandbox/local-factory-sandbox.js +32 -7
- package/dist/sandbox/local-factory-sandbox.js.map +1 -1
- package/dist/sandbox/materialization.js +1 -2
- package/dist/sandbox/session-retirement.js +1 -2
- package/dist/sandbox/session-sandbox.js +1 -2
- package/dist/sandbox/workdir.js +1 -2
- package/dist/secret-encryption.js +1 -2
- package/dist/server-error.js +1 -2
- package/dist/session/credential-policy.js +1 -2
- package/dist/session/default-model-hydration.js +1 -2
- package/dist/session/environment-repositories.js +1 -2
- package/dist/session/environment-state-processor.d.ts +0 -1
- package/dist/session/environment-state-processor.d.ts.map +1 -1
- package/dist/session/environment-state-processor.js +2 -3
- package/dist/session/environment-state-processor.js.map +1 -1
- package/dist/session/factory-session.js +1 -2
- package/dist/session/filesystem-capture.js +2 -3
- package/dist/session/filesystem-capture.js.map +1 -1
- package/dist/session/first-exec-capture.js +2 -3
- package/dist/session/first-exec-capture.js.map +1 -1
- package/dist/session/first-message-capture.js +1 -2
- package/dist/session/live-sessions.js +1 -2
- package/dist/session/memory-settings-hydration.js +1 -2
- package/dist/session/org-seed.js +1 -2
- package/dist/session/reply-credential-processor.js +1 -2
- package/dist/session/resource-migration.js +1 -2
- package/dist/session/run-audit.js +1 -2
- package/dist/session/session-threads.js +1 -2
- package/dist/session/session-title.js +1 -2
- package/dist/session/shell-commands.js +1 -2
- package/dist/session/source-control-tools.js +2 -3
- package/dist/session/thinking-default.d.ts +1 -1
- package/dist/session/thinking-default.d.ts.map +1 -1
- package/dist/session/thinking-default.js +11 -13
- package/dist/session/thinking-default.js.map +1 -1
- package/dist/session/thread-session-stamp.js +1 -2
- package/dist/session/thread-title-mirror.js +1 -2
- package/dist/session/thread-title-mirror.js.map +1 -1
- package/dist/session/work-item-repository.js +1 -2
- package/dist/session-owner-signal.js +1 -2
- package/dist/skills/catalog.js +1 -2
- package/dist/skills/service.js +1 -2
- package/dist/spa-static.js +1 -2
- package/dist/state-signing.js +1 -2
- package/dist/storage/domains/audit/actions.js +1 -2
- package/dist/storage/domains/audit/actors.js +1 -2
- package/dist/storage/domains/audit/agent-audit.js +1 -2
- package/dist/storage/domains/audit/base.js +1 -2
- package/dist/storage/domains/audit/domain.js +1 -2
- package/dist/storage/domains/audit/wire.js +1 -2
- package/dist/storage/domains/channel-identity/base.js +1 -2
- package/dist/storage/domains/comments/activity.js +1 -2
- package/dist/storage/domains/comments/actor.js +1 -2
- package/dist/storage/domains/comments/base.js +1 -2
- package/dist/storage/domains/comments/domain.js +1 -2
- package/dist/storage/domains/comments/feed-context.js +1 -2
- package/dist/storage/domains/comments/parse.js +1 -2
- package/dist/storage/domains/comments/routes.js +1 -2
- package/dist/storage/domains/comments/schema.js +1 -2
- package/dist/storage/domains/comments/wire.js +1 -2
- package/dist/storage/domains/credentials/base.d.ts +4 -1
- package/dist/storage/domains/credentials/base.d.ts.map +1 -1
- package/dist/storage/domains/credentials/base.js +40 -44
- package/dist/storage/domains/credentials/base.js.map +1 -1
- package/dist/storage/domains/custom-providers/base.js +1 -2
- package/dist/storage/domains/filesystem/base.js +1 -2
- package/dist/storage/domains/intake/base.d.ts +5 -0
- package/dist/storage/domains/intake/base.d.ts.map +1 -1
- package/dist/storage/domains/intake/base.js +10 -2
- package/dist/storage/domains/intake/base.js.map +1 -1
- package/dist/storage/domains/integrations/base.js +1 -2
- package/dist/storage/domains/memory-settings/base.js +1 -2
- package/dist/storage/domains/model-defaults/base.js +1 -2
- package/dist/storage/domains/projects/base.d.ts +0 -1
- package/dist/storage/domains/projects/base.d.ts.map +1 -1
- package/dist/storage/domains/projects/base.js +5 -6
- package/dist/storage/domains/projects/base.js.map +1 -1
- package/dist/storage/domains/queue-health/base.js +1 -2
- package/dist/storage/domains/source-control/base.js +1 -2
- package/dist/storage/domains/source-control/inmemory.js +1 -2
- package/dist/storage/domains/work-items/base.js +1 -2
- package/dist/storage/domains/work-items/board-version.js +1 -2
- package/dist/storage/domains/work-items/metrics.js +1 -2
- package/dist/telemetry-types.js +1 -2
- package/dist/telemetry.js +1 -2
- package/dist/timing.js +1 -2
- package/dist/tools/annotations.js +1 -2
- package/dist/tools/approval-tools.js +1 -2
- package/dist/tools/deliver.js +2 -3
- package/dist/tools/index.js +1 -2
- package/dist/tools/messaging-tools.js +1 -2
- package/dist/tools/permissions.js +1 -2
- package/dist/tools/read-tools.js +1 -2
- package/dist/tools/reports.js +1 -2
- package/dist/tools/run-watch.d.ts +0 -2
- package/dist/tools/run-watch.d.ts.map +1 -1
- package/dist/tools/run-watch.js +4 -44
- package/dist/tools/run-watch.js.map +1 -1
- package/dist/tools/sandbox-tools.js +1 -2
- package/dist/tools/scope.js +2 -3
- package/dist/tools/session-tools.js +1 -2
- package/dist/tools/sessions-state-processor.js +1 -2
- package/dist/tools/side-sessions.js +1 -2
- package/dist/tools/work-item-tools.js +1 -2
- package/dist/work-item-branch.js +1 -2
- package/dist/work-item-branch.js.map +1 -1
- package/dist/work-items/create-work-item.js +1 -2
- package/dist/work-items/decision-actions.js +1 -2
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +1 -3
- package/dist/workspace.js.map +1 -1
- package/factory-skills/factory-gitlab-review/SKILL.md +1 -1
- package/factory-skills/factory-plan/SKILL.md +1 -1
- package/factory-skills/factory-rereview/SKILL.md +14 -3
- package/factory-skills/factory-review/SKILL.md +14 -3
- package/factory-skills/factory-self-review/SKILL.md +1 -1
- package/factory-skills/factory-triage/SKILL.md +52 -29
- package/package.json +19 -17
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createPlaintextFactorySecretEncryption } from "../../../secret-encryption.js";
|
|
2
2
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
3
|
-
|
|
3
|
+
// src/storage/domains/credentials/base.ts
|
|
4
4
|
/** Mirror of `AuthStorage.getApiKey()`'s expiry check. */
|
|
5
5
|
function isOAuthCredentialExpired(credential, now = Date.now()) {
|
|
6
6
|
return now >= credential.expires;
|
|
@@ -18,7 +18,11 @@ const MODEL_CREDENTIALS_SCHEMA = {
|
|
|
18
18
|
type: { type: "text" },
|
|
19
19
|
data: { type: "json" },
|
|
20
20
|
created_at: { type: "timestamp" },
|
|
21
|
-
updated_at: { type: "timestamp" }
|
|
21
|
+
updated_at: { type: "timestamp" },
|
|
22
|
+
refresh_failed_at: {
|
|
23
|
+
type: "timestamp",
|
|
24
|
+
nullable: true
|
|
25
|
+
}
|
|
22
26
|
},
|
|
23
27
|
uniqueIndexes: [{
|
|
24
28
|
name: "model_provider_credentials_user_unique",
|
|
@@ -107,6 +111,15 @@ var ModelCredentialsStorage = class extends FactoryStorageDomain {
|
|
|
107
111
|
async #decryptCredential(value) {
|
|
108
112
|
return (await this.encryption.decrypt(value)).value;
|
|
109
113
|
}
|
|
114
|
+
async #toRecord(row, scope) {
|
|
115
|
+
return {
|
|
116
|
+
provider: row.provider,
|
|
117
|
+
scope,
|
|
118
|
+
credential: await this.#decryptCredential(row.data),
|
|
119
|
+
updatedAt: row.updated_at,
|
|
120
|
+
refreshFailedAt: row.refresh_failed_at ?? void 0
|
|
121
|
+
};
|
|
122
|
+
}
|
|
110
123
|
async #migrateCredential(id) {
|
|
111
124
|
await this.#db.updateAtomic("model_provider_credentials", { id }, async (row) => {
|
|
112
125
|
const decrypted = await this.encryption.decrypt(row.data);
|
|
@@ -126,7 +139,8 @@ var ModelCredentialsStorage = class extends FactoryStorageDomain {
|
|
|
126
139
|
const update = async () => this.#db.updateMany("model_provider_credentials", where, {
|
|
127
140
|
type: credential.type,
|
|
128
141
|
data: encrypted,
|
|
129
|
-
updated_at: /* @__PURE__ */ new Date()
|
|
142
|
+
updated_at: /* @__PURE__ */ new Date(),
|
|
143
|
+
refresh_failed_at: null
|
|
130
144
|
});
|
|
131
145
|
let lastError;
|
|
132
146
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
@@ -163,45 +177,20 @@ var ModelCredentialsStorage = class extends FactoryStorageDomain {
|
|
|
163
177
|
org_id: orgId,
|
|
164
178
|
user_id: null
|
|
165
179
|
})]);
|
|
166
|
-
return Promise.all([...userRows.map(
|
|
167
|
-
provider: row.provider,
|
|
168
|
-
scope: "user",
|
|
169
|
-
credential: await this.#decryptCredential(row.data),
|
|
170
|
-
updatedAt: row.updated_at
|
|
171
|
-
})), ...orgRows.map(async (row) => ({
|
|
172
|
-
provider: row.provider,
|
|
173
|
-
scope: "org",
|
|
174
|
-
credential: await this.#decryptCredential(row.data),
|
|
175
|
-
updatedAt: row.updated_at
|
|
176
|
-
}))]);
|
|
180
|
+
return Promise.all([...userRows.map((row) => this.#toRecord(row, "user")), ...orgRows.map((row) => this.#toRecord(row, "org"))]);
|
|
177
181
|
}
|
|
178
182
|
/** Resolve a provider credential from exactly one tenancy scope. */
|
|
179
183
|
async resolveCredential(orgId, userId, provider, scope) {
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
provider,
|
|
184
|
-
user_id: userId
|
|
185
|
-
});
|
|
186
|
-
return row ? {
|
|
187
|
-
provider: row.provider,
|
|
188
|
-
scope: "user",
|
|
189
|
-
credential: await this.#decryptCredential(row.data)
|
|
190
|
-
} : void 0;
|
|
184
|
+
const tenant = scope === "org" ? { orgId } : {
|
|
185
|
+
orgId,
|
|
186
|
+
userId
|
|
191
187
|
};
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return row ? {
|
|
199
|
-
provider: row.provider,
|
|
200
|
-
scope: "org",
|
|
201
|
-
credential: await this.#decryptCredential(row.data)
|
|
202
|
-
} : void 0;
|
|
203
|
-
};
|
|
204
|
-
return scope === "org" ? readOrg() : readUser();
|
|
188
|
+
const row = await this.#db.findOne("model_provider_credentials", tenantWhere(tenant, provider));
|
|
189
|
+
return row ? {
|
|
190
|
+
provider: row.provider,
|
|
191
|
+
scope,
|
|
192
|
+
credential: await this.#decryptCredential(row.data)
|
|
193
|
+
} : void 0;
|
|
205
194
|
}
|
|
206
195
|
/**
|
|
207
196
|
* Refresh the tenant's OAuth credential under the backend's atomic
|
|
@@ -209,10 +198,12 @@ var ModelCredentialsStorage = class extends FactoryStorageDomain {
|
|
|
209
198
|
* rotating refresh tokens. The expiry is re-checked under the lock —
|
|
210
199
|
* another replica may have refreshed already, in which case `refreshFn` is
|
|
211
200
|
* skipped and the fresh credential is returned. Returns `undefined` when no
|
|
212
|
-
* OAuth row exists for the tenant.
|
|
201
|
+
* OAuth row exists for the tenant. A failed `refreshFn` is recorded on the
|
|
202
|
+
* row (surfaced as `CredentialRecord.refreshFailedAt`) and rethrown.
|
|
213
203
|
*/
|
|
214
204
|
async refreshOAuth(tenant, provider, refreshFn) {
|
|
215
205
|
let result;
|
|
206
|
+
let failure;
|
|
216
207
|
await this.#db.updateAtomic("model_provider_credentials", tenantWhere(tenant, provider), async (row) => {
|
|
217
208
|
const decrypted = await this.encryption.decrypt(row.data);
|
|
218
209
|
if (decrypted.value.type !== "oauth") return null;
|
|
@@ -221,13 +212,19 @@ var ModelCredentialsStorage = class extends FactoryStorageDomain {
|
|
|
221
212
|
result = current;
|
|
222
213
|
return decrypted.needsReencryption ? { data: await this.encryption.encrypt(current) } : null;
|
|
223
214
|
}
|
|
224
|
-
|
|
225
|
-
|
|
215
|
+
try {
|
|
216
|
+
result = await refreshFn(current);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
failure = { error };
|
|
219
|
+
return { refresh_failed_at: /* @__PURE__ */ new Date() };
|
|
220
|
+
}
|
|
226
221
|
return {
|
|
227
|
-
data: await this.encryption.encrypt(
|
|
228
|
-
updated_at: /* @__PURE__ */ new Date()
|
|
222
|
+
data: await this.encryption.encrypt(result),
|
|
223
|
+
updated_at: /* @__PURE__ */ new Date(),
|
|
224
|
+
refresh_failed_at: null
|
|
229
225
|
};
|
|
230
226
|
});
|
|
227
|
+
if (failure) throw failure.error;
|
|
231
228
|
return result;
|
|
232
229
|
}
|
|
233
230
|
/** Persist a pending login flow started by a web route. */
|
|
@@ -288,7 +285,6 @@ var ModelCredentialsStorage = class extends FactoryStorageDomain {
|
|
|
288
285
|
await this.#db.deleteMany("oauth_login_sessions", { session_id: sessionId });
|
|
289
286
|
}
|
|
290
287
|
};
|
|
291
|
-
//#endregion
|
|
292
288
|
export { MODEL_CREDENTIALS_SCHEMA, ModelCredentialsStorage, OAUTH_LOGIN_SESSIONS_SCHEMA, isOAuthCredentialExpired };
|
|
293
289
|
|
|
294
290
|
//# sourceMappingURL=base.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","names":[],"sources":["../../../../src/storage/domains/credentials/base.ts"],"sourcesContent":["/**\n * Model provider credentials domain — tenant-scoped OAuth tokens and API keys\n * for model providers (Anthropic/Claude Max, OpenAI Codex, GitHub Copilot,\n * xAI, plus plain API-key providers).\n *\n * Tenancy is two-level:\n * - **user-scoped** rows (`userId` present): personal plan OAuth tokens and\n * personal API keys. OAuth plan tokens are ONLY ever user-scoped — they are\n * personal subscriptions, and sharing one would bill/rate-limit a single\n * account for the whole org.\n * - **org-scoped** rows (`userId` absent): shared API keys set by an org\n * admin, inherited by every member.\n *\n * Model calls resolve exactly one scope: user or org. Deployed tenant stores\n * never fall back to the other scope or implicitly borrow server environment keys.\n *\n * Secrets posture: credentials are stored server-side only and never returned\n * to the client (same as `linear_connections.access_token`). Encryption at\n * rest is out of scope, matching the existing posture.\n *\n * The domain also owns `oauth_login_sessions`: pending web login flows\n * (paste-code PKCE verifiers, device-code poll state) persisted server-side so\n * any replica can complete or poll a flow started on another.\n */\n\nimport type { AuthCredential, OAuthCredential } from '@mastra/code-sdk/auth/types';\nimport { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, CollectionWhere, FactoryStorageOps } from '@mastra/core/storage';\nimport { createPlaintextFactorySecretEncryption } from '../../../secret-encryption.js';\nimport type { FactorySecretEncryption } from '../../../secret-encryption.js';\n\n/** Owning tenant of a credential row. `userId` absent = org-scoped row. */\nexport interface CredentialTenant {\n orgId: string;\n userId?: string;\n}\n\n/** Which tenancy level a credential row lives at. */\nexport type CredentialScope = 'user' | 'org';\n\n/** One stored credential, annotated with its scope. */\nexport interface CredentialRecord {\n provider: string;\n scope: CredentialScope;\n credential: AuthCredential;\n updatedAt: Date;\n}\n\n/** Result of per-caller resolution: the winning credential and its scope. */\nexport interface ResolvedCredential {\n provider: string;\n scope: CredentialScope;\n credential: AuthCredential;\n}\n\n/** Kind of pending web login flow a session row tracks. */\nexport type LoginSessionKind = 'paste-code' | 'device-code';\n\n/** Scope the completed credential should be written to. */\nexport type LoginCredentialScope = 'user' | 'org';\n\n/** One pending OAuth login flow, persisted so any replica can continue it. */\nexport interface LoginSessionRow {\n sessionId: string;\n orgId: string;\n userId: string;\n provider: string;\n kind: LoginSessionKind;\n /** Where the completed credential lands; absent rows default to `'user'`. */\n credentialScope?: LoginCredentialScope;\n /** Serialized flow state (PKCE verifier, device-code pending state, ...). */\n pending: Record<string, unknown>;\n expiresAt: Date;\n /** Earliest time the next upstream poll is allowed (device-code flows). */\n nextPollAt: Date | null;\n createdAt: Date;\n}\n\nexport interface CreateLoginSessionInput {\n sessionId: string;\n orgId: string;\n userId: string;\n provider: string;\n kind: LoginSessionKind;\n credentialScope?: LoginCredentialScope;\n pending: Record<string, unknown>;\n expiresAt: Date;\n nextPollAt?: Date | null;\n}\n\n/** Mirror of `AuthStorage.getApiKey()`'s expiry check. */\nexport function isOAuthCredentialExpired(credential: OAuthCredential, now = Date.now()): boolean {\n return now >= credential.expires;\n}\n\nexport const MODEL_CREDENTIALS_SCHEMA: CollectionSchema = {\n name: 'model_provider_credentials',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n user_id: { type: 'text', nullable: true },\n provider: { type: 'text' },\n type: { type: 'text' },\n data: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [\n // Scope is encoded in `user_id` nullability (NULL = org-scoped shared\n // row), enforced by two partial unique indexes.\n {\n name: 'model_provider_credentials_user_unique',\n columns: ['org_id', 'user_id', 'provider'],\n whereNotNull: 'user_id',\n },\n { name: 'model_provider_credentials_org_unique', columns: ['org_id', 'provider'], whereNull: 'user_id' },\n ],\n};\n\nexport const OAUTH_LOGIN_SESSIONS_SCHEMA: CollectionSchema = {\n name: 'oauth_login_sessions',\n columns: {\n session_id: { type: 'text', primaryKey: true },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n provider: { type: 'text' },\n kind: { type: 'text' },\n credential_scope: { type: 'text', nullable: true },\n pending: { type: 'json' },\n expires_at: { type: 'timestamp' },\n next_poll_at: { type: 'timestamp', nullable: true },\n created_at: { type: 'timestamp' },\n },\n};\n\n/** Column shape of one `model_provider_credentials` row as returned by ops. */\ninterface CredentialDbRow extends Record<string, unknown> {\n id: string;\n provider: string;\n user_id: string | null;\n data: unknown;\n updated_at: Date;\n}\n\n/** Column shape of one `oauth_login_sessions` row as returned by ops. */\ninterface LoginSessionDbRow extends Record<string, unknown> {\n session_id: string;\n org_id: string;\n user_id: string;\n provider: string;\n kind: LoginSessionKind;\n credential_scope: LoginCredentialScope | null;\n pending: Record<string, unknown>;\n expires_at: Date;\n next_poll_at: Date | null;\n created_at: Date;\n}\n\nfunction toSessionRow(db: LoginSessionDbRow): LoginSessionRow {\n return {\n sessionId: db.session_id,\n orgId: db.org_id,\n userId: db.user_id,\n provider: db.provider,\n kind: db.kind,\n ...(db.credential_scope ? { credentialScope: db.credential_scope } : {}),\n pending: db.pending,\n expiresAt: db.expires_at,\n nextPollAt: db.next_poll_at,\n createdAt: db.created_at,\n };\n}\n\n/** Filter selecting exactly the tenant's row for a provider (`null` = org row). */\nfunction tenantWhere(tenant: CredentialTenant, provider: string): CollectionWhere {\n return { org_id: tenant.orgId, provider, user_id: tenant.userId ?? null };\n}\n\n/**\n * Model-credentials storage, written once against the generic\n * `FactoryStorageOps` surface. `refreshOAuth()` and `claimLoginSession()`\n * ride `updateAtomic` so concurrent replicas serialize instead of\n * invalidating each other's rotating tokens / double-claiming a flow.\n */\nexport class ModelCredentialsStorage extends FactoryStorageDomain {\n constructor(private readonly encryption: FactorySecretEncryption = createPlaintextFactorySecretEncryption()) {\n super('model-credentials');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([MODEL_CREDENTIALS_SCHEMA, OAUTH_LOGIN_SESSIONS_SCHEMA]);\n const rows = await this.ops.findMany<CredentialDbRow>('model_provider_credentials', {});\n await Promise.all(rows.map(row => this.#migrateCredential(row.id)));\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('oauth_login_sessions', {});\n await this.ops.deleteMany('model_provider_credentials', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async #decryptCredential(value: unknown): Promise<AuthCredential> {\n return (await this.encryption.decrypt<AuthCredential>(value)).value;\n }\n\n async #migrateCredential(id: string): Promise<void> {\n await this.#db.updateAtomic<CredentialDbRow>('model_provider_credentials', { id }, async row => {\n const decrypted = await this.encryption.decrypt<AuthCredential>(row.data);\n if (!decrypted.needsReencryption) return null;\n return { data: await this.encryption.encrypt(decrypted.value) };\n });\n }\n\n /** Read the tenant's credential for a provider at exactly that scope. */\n async getCredential(tenant: CredentialTenant, provider: string): Promise<AuthCredential | undefined> {\n const row = await this.#db.findOne<CredentialDbRow>('model_provider_credentials', tenantWhere(tenant, provider));\n return row ? this.#decryptCredential(row.data) : undefined;\n }\n\n /** Upsert the tenant's credential (`created_at` is preserved on update). */\n async setCredential(tenant: CredentialTenant, provider: string, credential: AuthCredential): Promise<void> {\n const where = tenantWhere(tenant, provider);\n const encrypted = await this.encryption.encrypt(credential);\n const update = async () =>\n this.#db.updateMany('model_provider_credentials', where, {\n type: credential.type,\n data: encrypted,\n updated_at: new Date(),\n });\n\n let lastError: unknown;\n for (let attempt = 0; attempt < 2; attempt++) {\n if ((await update()) > 0) return;\n\n const now = new Date();\n try {\n await this.#db.insertOne<CredentialDbRow>('model_provider_credentials', {\n org_id: tenant.orgId,\n user_id: tenant.userId ?? null,\n provider,\n type: credential.type,\n data: encrypted,\n created_at: now,\n updated_at: now,\n });\n return;\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n lastError = error;\n }\n }\n throw lastError;\n }\n\n /** Delete the tenant's credential at exactly that scope. True when a row was removed. */\n async removeCredential(tenant: CredentialTenant, provider: string): Promise<boolean> {\n const deleted = await this.#db.deleteMany('model_provider_credentials', tenantWhere(tenant, provider));\n return deleted > 0;\n }\n\n /** All credentials visible to a user: their own rows plus the org's shared rows. */\n async listCredentials(orgId: string, userId: string): Promise<CredentialRecord[]> {\n // SQL `IN` never matches NULL, so the org rows need their own query.\n const [userRows, orgRows] = await Promise.all([\n this.#db.findMany<CredentialDbRow>('model_provider_credentials', { org_id: orgId, user_id: userId }),\n this.#db.findMany<CredentialDbRow>('model_provider_credentials', { org_id: orgId, user_id: null }),\n ]);\n return Promise.all([\n ...userRows.map(async row => ({\n provider: row.provider,\n scope: 'user' as const,\n credential: await this.#decryptCredential(row.data),\n updatedAt: row.updated_at,\n })),\n ...orgRows.map(async row => ({\n provider: row.provider,\n scope: 'org' as const,\n credential: await this.#decryptCredential(row.data),\n updatedAt: row.updated_at,\n })),\n ]);\n }\n\n /** Resolve a provider credential from exactly one tenancy scope. */\n async resolveCredential(\n orgId: string,\n userId: string,\n provider: string,\n scope: CredentialScope,\n ): Promise<ResolvedCredential | undefined> {\n const readUser = async (): Promise<ResolvedCredential | undefined> => {\n const row = await this.#db.findOne<CredentialDbRow>('model_provider_credentials', {\n org_id: orgId,\n provider,\n user_id: userId,\n });\n return row\n ? { provider: row.provider, scope: 'user', credential: await this.#decryptCredential(row.data) }\n : undefined;\n };\n const readOrg = async (): Promise<ResolvedCredential | undefined> => {\n const row = await this.#db.findOne<CredentialDbRow>('model_provider_credentials', {\n org_id: orgId,\n provider,\n user_id: null,\n });\n return row\n ? { provider: row.provider, scope: 'org', credential: await this.#decryptCredential(row.data) }\n : undefined;\n };\n return scope === 'org' ? readOrg() : readUser();\n }\n\n /**\n * Refresh the tenant's OAuth credential under the backend's atomic\n * read-modify-write so concurrent replicas don't invalidate each other's\n * rotating refresh tokens. The expiry is re-checked under the lock —\n * another replica may have refreshed already, in which case `refreshFn` is\n * skipped and the fresh credential is returned. Returns `undefined` when no\n * OAuth row exists for the tenant.\n */\n async refreshOAuth(\n tenant: CredentialTenant,\n provider: string,\n refreshFn: (current: OAuthCredential) => Promise<OAuthCredential>,\n ): Promise<OAuthCredential | undefined> {\n let result: OAuthCredential | undefined;\n await this.#db.updateAtomic<CredentialDbRow>(\n 'model_provider_credentials',\n tenantWhere(tenant, provider),\n async row => {\n const decrypted = await this.encryption.decrypt<AuthCredential>(row.data);\n if (decrypted.value.type !== 'oauth') return null;\n const current = decrypted.value;\n // Re-check under the lock: another replica may have refreshed while we waited.\n if (!isOAuthCredentialExpired(current)) {\n result = current;\n return decrypted.needsReencryption ? { data: await this.encryption.encrypt(current) } : null;\n }\n const next = await refreshFn(current);\n result = next;\n return { data: await this.encryption.encrypt(next), updated_at: new Date() };\n },\n );\n return result;\n }\n\n /** Persist a pending login flow started by a web route. */\n async createLoginSession(input: CreateLoginSessionInput): Promise<LoginSessionRow> {\n const inserted = await this.#db.insertOne<LoginSessionDbRow>('oauth_login_sessions', {\n session_id: input.sessionId,\n org_id: input.orgId,\n user_id: input.userId,\n provider: input.provider,\n kind: input.kind,\n credential_scope: input.credentialScope ?? null,\n pending: input.pending,\n expires_at: input.expiresAt,\n next_poll_at: input.nextPollAt ?? null,\n created_at: new Date(),\n });\n return toSessionRow(inserted);\n }\n\n /**\n * Read a pending login flow. An expired session is deleted on read (TTL\n * cleanup) and reported as absent.\n */\n async getLoginSession(sessionId: string): Promise<LoginSessionRow | undefined> {\n const row = await this.#db.findOne<LoginSessionDbRow>('oauth_login_sessions', { session_id: sessionId });\n if (!row) return undefined;\n if (row.expires_at.getTime() <= Date.now()) {\n await this.#db.deleteMany('oauth_login_sessions', { session_id: sessionId });\n return undefined;\n }\n return toSessionRow(row);\n }\n\n /**\n * Atomically claim a due login session for one upstream completion/poll attempt.\n * Returns undefined when the session is missing, expired, owned by another\n * tenant/provider, or already claimed by a concurrent request.\n */\n async claimLoginSession(\n sessionId: string,\n owner: Pick<LoginSessionRow, 'orgId' | 'userId' | 'provider' | 'kind'>,\n ): Promise<LoginSessionRow | undefined> {\n const now = Date.now();\n let claimed = false;\n const updated = await this.#db.updateAtomic<LoginSessionDbRow>(\n 'oauth_login_sessions',\n { session_id: sessionId },\n row => {\n if (\n row.org_id !== owner.orgId ||\n row.user_id !== owner.userId ||\n row.provider !== owner.provider ||\n row.kind !== owner.kind\n ) {\n return null;\n }\n if (row.expires_at.getTime() <= now) return null;\n if (row.next_poll_at && row.next_poll_at.getTime() > now) return null;\n claimed = true;\n // Park the next poll at expiry so a concurrent claim loses until the\n // claimer either touches the session forward or deletes it.\n return { next_poll_at: row.expires_at };\n },\n );\n return claimed && updated ? toSessionRow(updated) : undefined;\n }\n\n /** Update a pending flow's serialized state and/or next allowed poll time. */\n async touchLoginSession(\n sessionId: string,\n updates: { pending?: Record<string, unknown>; nextPollAt?: Date | null },\n ): Promise<void> {\n const set: Record<string, unknown> = {};\n if (updates.pending !== undefined) set.pending = updates.pending;\n if (updates.nextPollAt !== undefined) set.next_poll_at = updates.nextPollAt;\n if (Object.keys(set).length === 0) return;\n await this.#db.updateMany('oauth_login_sessions', { session_id: sessionId }, set);\n }\n\n /** Remove a pending login flow (completed, cancelled, or failed). */\n async deleteLoginSession(sessionId: string): Promise<void> {\n await this.#db.deleteMany('oauth_login_sessions', { session_id: sessionId });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"base.js","names":[],"sources":["../../../../src/storage/domains/credentials/base.ts"],"sourcesContent":["/**\n * Model provider credentials domain — tenant-scoped OAuth tokens and API keys\n * for model providers (Anthropic/Claude Max, OpenAI Codex, GitHub Copilot,\n * xAI, plus plain API-key providers).\n *\n * Tenancy is two-level:\n * - **user-scoped** rows (`userId` present): personal plan OAuth tokens and\n * personal API keys. OAuth plan tokens are ONLY ever user-scoped — they are\n * personal subscriptions, and sharing one would bill/rate-limit a single\n * account for the whole org.\n * - **org-scoped** rows (`userId` absent): shared API keys set by an org\n * admin, inherited by every member.\n *\n * Model calls resolve exactly one scope: user or org. Deployed tenant stores\n * never fall back to the other scope or implicitly borrow server environment keys.\n *\n * Secrets posture: credentials are stored server-side only and never returned\n * to the client (same as `linear_connections.access_token`). Encryption at\n * rest is out of scope, matching the existing posture.\n *\n * The domain also owns `oauth_login_sessions`: pending web login flows\n * (paste-code PKCE verifiers, device-code poll state) persisted server-side so\n * any replica can complete or poll a flow started on another.\n */\n\nimport type { AuthCredential, OAuthCredential } from '@mastra/code-sdk/auth/types';\nimport { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, CollectionWhere, FactoryStorageOps } from '@mastra/core/storage';\nimport { createPlaintextFactorySecretEncryption } from '../../../secret-encryption.js';\nimport type { FactorySecretEncryption } from '../../../secret-encryption.js';\n\n/** Owning tenant of a credential row. `userId` absent = org-scoped row. */\nexport interface CredentialTenant {\n orgId: string;\n userId?: string;\n}\n\n/** Which tenancy level a credential row lives at. */\nexport type CredentialScope = 'user' | 'org';\n\n/** One stored credential, annotated with its scope. */\nexport interface CredentialRecord {\n provider: string;\n scope: CredentialScope;\n credential: AuthCredential;\n updatedAt: Date;\n /** When the last OAuth token refresh failed; cleared by the next successful refresh or a new sign-in. */\n refreshFailedAt?: Date;\n}\n\n/** Result of per-caller resolution: the winning credential and its scope. */\nexport interface ResolvedCredential {\n provider: string;\n scope: CredentialScope;\n credential: AuthCredential;\n}\n\n/** Kind of pending web login flow a session row tracks. */\nexport type LoginSessionKind = 'paste-code' | 'device-code';\n\n/** Scope the completed credential should be written to. */\nexport type LoginCredentialScope = 'user' | 'org';\n\n/** One pending OAuth login flow, persisted so any replica can continue it. */\nexport interface LoginSessionRow {\n sessionId: string;\n orgId: string;\n userId: string;\n provider: string;\n kind: LoginSessionKind;\n /** Where the completed credential lands; absent rows default to `'user'`. */\n credentialScope?: LoginCredentialScope;\n /** Serialized flow state (PKCE verifier, device-code pending state, ...). */\n pending: Record<string, unknown>;\n expiresAt: Date;\n /** Earliest time the next upstream poll is allowed (device-code flows). */\n nextPollAt: Date | null;\n createdAt: Date;\n}\n\nexport interface CreateLoginSessionInput {\n sessionId: string;\n orgId: string;\n userId: string;\n provider: string;\n kind: LoginSessionKind;\n credentialScope?: LoginCredentialScope;\n pending: Record<string, unknown>;\n expiresAt: Date;\n nextPollAt?: Date | null;\n}\n\n/** Mirror of `AuthStorage.getApiKey()`'s expiry check. */\nexport function isOAuthCredentialExpired(credential: OAuthCredential, now = Date.now()): boolean {\n return now >= credential.expires;\n}\n\nexport const MODEL_CREDENTIALS_SCHEMA: CollectionSchema = {\n name: 'model_provider_credentials',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n user_id: { type: 'text', nullable: true },\n provider: { type: 'text' },\n type: { type: 'text' },\n data: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n refresh_failed_at: { type: 'timestamp', nullable: true },\n },\n uniqueIndexes: [\n // Scope is encoded in `user_id` nullability (NULL = org-scoped shared\n // row), enforced by two partial unique indexes.\n {\n name: 'model_provider_credentials_user_unique',\n columns: ['org_id', 'user_id', 'provider'],\n whereNotNull: 'user_id',\n },\n { name: 'model_provider_credentials_org_unique', columns: ['org_id', 'provider'], whereNull: 'user_id' },\n ],\n};\n\nexport const OAUTH_LOGIN_SESSIONS_SCHEMA: CollectionSchema = {\n name: 'oauth_login_sessions',\n columns: {\n session_id: { type: 'text', primaryKey: true },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n provider: { type: 'text' },\n kind: { type: 'text' },\n credential_scope: { type: 'text', nullable: true },\n pending: { type: 'json' },\n expires_at: { type: 'timestamp' },\n next_poll_at: { type: 'timestamp', nullable: true },\n created_at: { type: 'timestamp' },\n },\n};\n\n/** Column shape of one `model_provider_credentials` row as returned by ops. */\ninterface CredentialDbRow extends Record<string, unknown> {\n id: string;\n provider: string;\n user_id: string | null;\n data: unknown;\n updated_at: Date;\n refresh_failed_at: Date | null;\n}\n\n/** Column shape of one `oauth_login_sessions` row as returned by ops. */\ninterface LoginSessionDbRow extends Record<string, unknown> {\n session_id: string;\n org_id: string;\n user_id: string;\n provider: string;\n kind: LoginSessionKind;\n credential_scope: LoginCredentialScope | null;\n pending: Record<string, unknown>;\n expires_at: Date;\n next_poll_at: Date | null;\n created_at: Date;\n}\n\nfunction toSessionRow(db: LoginSessionDbRow): LoginSessionRow {\n return {\n sessionId: db.session_id,\n orgId: db.org_id,\n userId: db.user_id,\n provider: db.provider,\n kind: db.kind,\n ...(db.credential_scope ? { credentialScope: db.credential_scope } : {}),\n pending: db.pending,\n expiresAt: db.expires_at,\n nextPollAt: db.next_poll_at,\n createdAt: db.created_at,\n };\n}\n\n/** Filter selecting exactly the tenant's row for a provider (`null` = org row). */\nfunction tenantWhere(tenant: CredentialTenant, provider: string): CollectionWhere {\n return { org_id: tenant.orgId, provider, user_id: tenant.userId ?? null };\n}\n\n/**\n * Model-credentials storage, written once against the generic\n * `FactoryStorageOps` surface. `refreshOAuth()` and `claimLoginSession()`\n * ride `updateAtomic` so concurrent replicas serialize instead of\n * invalidating each other's rotating tokens / double-claiming a flow.\n */\nexport class ModelCredentialsStorage extends FactoryStorageDomain {\n constructor(private readonly encryption: FactorySecretEncryption = createPlaintextFactorySecretEncryption()) {\n super('model-credentials');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([MODEL_CREDENTIALS_SCHEMA, OAUTH_LOGIN_SESSIONS_SCHEMA]);\n const rows = await this.ops.findMany<CredentialDbRow>('model_provider_credentials', {});\n await Promise.all(rows.map(row => this.#migrateCredential(row.id)));\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('oauth_login_sessions', {});\n await this.ops.deleteMany('model_provider_credentials', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async #decryptCredential(value: unknown): Promise<AuthCredential> {\n return (await this.encryption.decrypt<AuthCredential>(value)).value;\n }\n\n async #toRecord(row: CredentialDbRow, scope: CredentialScope): Promise<CredentialRecord> {\n return {\n provider: row.provider,\n scope,\n credential: await this.#decryptCredential(row.data),\n updatedAt: row.updated_at,\n refreshFailedAt: row.refresh_failed_at ?? undefined,\n };\n }\n\n async #migrateCredential(id: string): Promise<void> {\n await this.#db.updateAtomic<CredentialDbRow>('model_provider_credentials', { id }, async row => {\n const decrypted = await this.encryption.decrypt<AuthCredential>(row.data);\n if (!decrypted.needsReencryption) return null;\n return { data: await this.encryption.encrypt(decrypted.value) };\n });\n }\n\n /** Read the tenant's credential for a provider at exactly that scope. */\n async getCredential(tenant: CredentialTenant, provider: string): Promise<AuthCredential | undefined> {\n const row = await this.#db.findOne<CredentialDbRow>('model_provider_credentials', tenantWhere(tenant, provider));\n return row ? this.#decryptCredential(row.data) : undefined;\n }\n\n /** Upsert the tenant's credential (`created_at` is preserved on update). */\n async setCredential(tenant: CredentialTenant, provider: string, credential: AuthCredential): Promise<void> {\n const where = tenantWhere(tenant, provider);\n const encrypted = await this.encryption.encrypt(credential);\n const update = async () =>\n this.#db.updateMany('model_provider_credentials', where, {\n type: credential.type,\n data: encrypted,\n updated_at: new Date(),\n refresh_failed_at: null,\n });\n\n let lastError: unknown;\n for (let attempt = 0; attempt < 2; attempt++) {\n if ((await update()) > 0) return;\n\n const now = new Date();\n try {\n await this.#db.insertOne<CredentialDbRow>('model_provider_credentials', {\n org_id: tenant.orgId,\n user_id: tenant.userId ?? null,\n provider,\n type: credential.type,\n data: encrypted,\n created_at: now,\n updated_at: now,\n });\n return;\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n lastError = error;\n }\n }\n throw lastError;\n }\n\n /** Delete the tenant's credential at exactly that scope. True when a row was removed. */\n async removeCredential(tenant: CredentialTenant, provider: string): Promise<boolean> {\n const deleted = await this.#db.deleteMany('model_provider_credentials', tenantWhere(tenant, provider));\n return deleted > 0;\n }\n\n /** All credentials visible to a user: their own rows plus the org's shared rows. */\n async listCredentials(orgId: string, userId: string): Promise<CredentialRecord[]> {\n // SQL `IN` never matches NULL, so the org rows need their own query.\n const [userRows, orgRows] = await Promise.all([\n this.#db.findMany<CredentialDbRow>('model_provider_credentials', { org_id: orgId, user_id: userId }),\n this.#db.findMany<CredentialDbRow>('model_provider_credentials', { org_id: orgId, user_id: null }),\n ]);\n return Promise.all([\n ...userRows.map(row => this.#toRecord(row, 'user')),\n ...orgRows.map(row => this.#toRecord(row, 'org')),\n ]);\n }\n\n /** Resolve a provider credential from exactly one tenancy scope. */\n async resolveCredential(\n orgId: string,\n userId: string,\n provider: string,\n scope: CredentialScope,\n ): Promise<ResolvedCredential | undefined> {\n const tenant = scope === 'org' ? { orgId } : { orgId, userId };\n const row = await this.#db.findOne<CredentialDbRow>('model_provider_credentials', tenantWhere(tenant, provider));\n return row ? { provider: row.provider, scope, credential: await this.#decryptCredential(row.data) } : undefined;\n }\n\n /**\n * Refresh the tenant's OAuth credential under the backend's atomic\n * read-modify-write so concurrent replicas don't invalidate each other's\n * rotating refresh tokens. The expiry is re-checked under the lock —\n * another replica may have refreshed already, in which case `refreshFn` is\n * skipped and the fresh credential is returned. Returns `undefined` when no\n * OAuth row exists for the tenant. A failed `refreshFn` is recorded on the\n * row (surfaced as `CredentialRecord.refreshFailedAt`) and rethrown.\n */\n async refreshOAuth(\n tenant: CredentialTenant,\n provider: string,\n refreshFn: (current: OAuthCredential) => Promise<OAuthCredential>,\n ): Promise<OAuthCredential | undefined> {\n let result: OAuthCredential | undefined;\n let failure: { error: unknown } | undefined;\n await this.#db.updateAtomic<CredentialDbRow>(\n 'model_provider_credentials',\n tenantWhere(tenant, provider),\n async row => {\n const decrypted = await this.encryption.decrypt<AuthCredential>(row.data);\n if (decrypted.value.type !== 'oauth') return null;\n const current = decrypted.value;\n // Re-check under the lock: another replica may have refreshed while we waited.\n if (!isOAuthCredentialExpired(current)) {\n result = current;\n return decrypted.needsReencryption ? { data: await this.encryption.encrypt(current) } : null;\n }\n try {\n result = await refreshFn(current);\n } catch (error) {\n failure = { error };\n return { refresh_failed_at: new Date() };\n }\n return { data: await this.encryption.encrypt(result), updated_at: new Date(), refresh_failed_at: null };\n },\n );\n if (failure) throw failure.error;\n return result;\n }\n\n /** Persist a pending login flow started by a web route. */\n async createLoginSession(input: CreateLoginSessionInput): Promise<LoginSessionRow> {\n const inserted = await this.#db.insertOne<LoginSessionDbRow>('oauth_login_sessions', {\n session_id: input.sessionId,\n org_id: input.orgId,\n user_id: input.userId,\n provider: input.provider,\n kind: input.kind,\n credential_scope: input.credentialScope ?? null,\n pending: input.pending,\n expires_at: input.expiresAt,\n next_poll_at: input.nextPollAt ?? null,\n created_at: new Date(),\n });\n return toSessionRow(inserted);\n }\n\n /**\n * Read a pending login flow. An expired session is deleted on read (TTL\n * cleanup) and reported as absent.\n */\n async getLoginSession(sessionId: string): Promise<LoginSessionRow | undefined> {\n const row = await this.#db.findOne<LoginSessionDbRow>('oauth_login_sessions', { session_id: sessionId });\n if (!row) return undefined;\n if (row.expires_at.getTime() <= Date.now()) {\n await this.#db.deleteMany('oauth_login_sessions', { session_id: sessionId });\n return undefined;\n }\n return toSessionRow(row);\n }\n\n /**\n * Atomically claim a due login session for one upstream completion/poll attempt.\n * Returns undefined when the session is missing, expired, owned by another\n * tenant/provider, or already claimed by a concurrent request.\n */\n async claimLoginSession(\n sessionId: string,\n owner: Pick<LoginSessionRow, 'orgId' | 'userId' | 'provider' | 'kind'>,\n ): Promise<LoginSessionRow | undefined> {\n const now = Date.now();\n let claimed = false;\n const updated = await this.#db.updateAtomic<LoginSessionDbRow>(\n 'oauth_login_sessions',\n { session_id: sessionId },\n row => {\n if (\n row.org_id !== owner.orgId ||\n row.user_id !== owner.userId ||\n row.provider !== owner.provider ||\n row.kind !== owner.kind\n ) {\n return null;\n }\n if (row.expires_at.getTime() <= now) return null;\n if (row.next_poll_at && row.next_poll_at.getTime() > now) return null;\n claimed = true;\n // Park the next poll at expiry so a concurrent claim loses until the\n // claimer either touches the session forward or deletes it.\n return { next_poll_at: row.expires_at };\n },\n );\n return claimed && updated ? toSessionRow(updated) : undefined;\n }\n\n /** Update a pending flow's serialized state and/or next allowed poll time. */\n async touchLoginSession(\n sessionId: string,\n updates: { pending?: Record<string, unknown>; nextPollAt?: Date | null },\n ): Promise<void> {\n const set: Record<string, unknown> = {};\n if (updates.pending !== undefined) set.pending = updates.pending;\n if (updates.nextPollAt !== undefined) set.next_poll_at = updates.nextPollAt;\n if (Object.keys(set).length === 0) return;\n await this.#db.updateMany('oauth_login_sessions', { session_id: sessionId }, set);\n }\n\n /** Remove a pending login flow (completed, cancelled, or failed). */\n async deleteLoginSession(sessionId: string): Promise<void> {\n await this.#db.deleteMany('oauth_login_sessions', { session_id: sessionId });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createPlaintextFactorySecretEncryption } from "../../../secret-encryption.js";
|
|
2
2
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
3
|
-
|
|
3
|
+
// src/storage/domains/custom-providers/base.ts
|
|
4
4
|
const CUSTOM_PROVIDERS_SCHEMA = {
|
|
5
5
|
name: "custom_providers",
|
|
6
6
|
columns: {
|
|
@@ -170,7 +170,6 @@ var CustomProvidersStorage = class extends FactoryStorageDomain {
|
|
|
170
170
|
}) > 0;
|
|
171
171
|
}
|
|
172
172
|
};
|
|
173
|
-
//#endregion
|
|
174
173
|
export { CUSTOM_PROVIDERS_SCHEMA, CustomProvidersStorage };
|
|
175
174
|
|
|
176
175
|
//# sourceMappingURL=base.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FactoryStorageDomain } from "@mastra/core/storage";
|
|
2
|
-
|
|
2
|
+
// src/storage/domains/filesystem/base.ts
|
|
3
3
|
const SNAPSHOTS = "filesystem_snapshots";
|
|
4
4
|
const FILESYSTEM_SCHEMAS = [{
|
|
5
5
|
name: SNAPSHOTS,
|
|
@@ -73,7 +73,6 @@ var FilesystemStorage = class extends FactoryStorageDomain {
|
|
|
73
73
|
return this.ops.deleteMany(SNAPSHOTS, { resource_id: args.resourceId });
|
|
74
74
|
}
|
|
75
75
|
};
|
|
76
|
-
//#endregion
|
|
77
76
|
export { FILESYSTEM_SCHEMAS, FilesystemStorage };
|
|
78
77
|
|
|
79
78
|
//# sourceMappingURL=base.js.map
|
|
@@ -77,6 +77,11 @@ export declare class IntakeStorage extends FactoryStorageDomain {
|
|
|
77
77
|
orgId: string;
|
|
78
78
|
config: IntakeConfig;
|
|
79
79
|
}): Promise<void>;
|
|
80
|
+
/** Overlay `config` onto the stored selections; integrations it omits keep their stored value. */
|
|
81
|
+
mergeConfig({ orgId, config }: {
|
|
82
|
+
orgId: string;
|
|
83
|
+
config: IntakeConfig;
|
|
84
|
+
}): Promise<IntakeConfig>;
|
|
80
85
|
/** Every source binding in the org, optionally narrowed to one integration. */
|
|
81
86
|
listBindings({ orgId, integrationId, }: {
|
|
82
87
|
orgId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/intake/base.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAwB,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,gBAAgB,EAAqB,MAAM,sBAAsB,CAAC;AAEhF,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,mEAAmE;IACnE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC3B,yBAAyB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpD;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAE3D,eAAO,MAAM,qBAAqB,EAAE,YAAiB,CAAC;AAEtD,eAAO,MAAM,0BAA0B,EAAE,gBAUxC,CAAC;AAEF,6HAA6H;AAC7H,eAAO,MAAM,kCAAkC,EAAE,gBAWhD,CAAC;AAEF,2IAA2I;AAC3I,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,YAAY,CAcpF;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,EAAE,gBAqB3C,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,EAAE,gBAqBxC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAiBD,yEAAyE;AACzE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,gBAAgB,EAAE,EACnC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACpC,gBAAgB,GAAG,SAAS,CAI9B;AAiBD,qBAAa,aAAc,SAAQ,oBAAoB;;;IAK/C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBrB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAWpC,SAAS,CAAC,EACd,KAAK,EACL,cAAc,GACf,EAAE;QACD,KAAK,EAAE,MAAM,CAAC;QACd;;;WAGG;QACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;KAC3B,GAAG,OAAO,CAAC,YAAY,CAAC;IASnB,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/intake/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
2
|
-
|
|
2
|
+
// src/storage/domains/intake/base.ts
|
|
3
3
|
/**
|
|
4
4
|
* Org-wide intake selections for every configured intake integration.
|
|
5
5
|
*
|
|
@@ -219,6 +219,15 @@ var IntakeStorage = class extends FactoryStorageDomain {
|
|
|
219
219
|
updated_at: now
|
|
220
220
|
});
|
|
221
221
|
}
|
|
222
|
+
/** Overlay `config` onto the stored selections; integrations it omits keep their stored value. */
|
|
223
|
+
async mergeConfig({ orgId, config }) {
|
|
224
|
+
const merged = Object.assign(Object.create(null), await this.getConfig({ orgId }), config);
|
|
225
|
+
await this.saveConfig({
|
|
226
|
+
orgId,
|
|
227
|
+
config: merged
|
|
228
|
+
});
|
|
229
|
+
return merged;
|
|
230
|
+
}
|
|
222
231
|
async #insertConfigIfAbsent(orgId, config) {
|
|
223
232
|
const now = /* @__PURE__ */ new Date();
|
|
224
233
|
try {
|
|
@@ -425,7 +434,6 @@ var IntakeStorage = class extends FactoryStorageDomain {
|
|
|
425
434
|
}, { isolationLevel: "serializable" });
|
|
426
435
|
}
|
|
427
436
|
};
|
|
428
|
-
//#endregion
|
|
429
437
|
export { DEFAULT_INTAKE_CONFIG, INTAKE_LABEL_ROUTES_SCHEMA, INTAKE_ORG_SETTINGS_SCHEMA, INTAKE_SOURCE_BINDINGS_SCHEMA, IntakeStorage, LEGACY_INTAKE_USER_SETTINGS_SCHEMA, mergeIntakeSelections, normalizeIntakeLabel, resolveIntakeLabelRoute };
|
|
430
438
|
|
|
431
439
|
//# sourceMappingURL=base.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","names":[],"sources":["../../../../src/storage/domains/intake/base.ts"],"sourcesContent":["/**\n * Org-wide intake selections for every configured intake integration.\n *\n * Integration ids are dynamic. Each integration contributes provider-neutral\n * sources through `FactoryIntegration.intake`; this domain only persists which\n * source ids the organization selected. The selection feeds shared boards, so\n * every member reads the same one.\n */\n\nimport { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\nexport interface IntakeSelection {\n enabled: boolean;\n /** Provider-owned source ids; `null` means nothing is selected. */\n sourceIds: string[] | null;\n repositoryByLinearProject?: Record<string, string>;\n}\n\nexport type IntakeConfig = Record<string, IntakeSelection>;\n\nexport const DEFAULT_INTAKE_CONFIG: IntakeConfig = {};\n\nexport const INTAKE_ORG_SETTINGS_SCHEMA: CollectionSchema = {\n name: 'intake_org_settings',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n config: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'intake_org_settings_org_unique', columns: ['org_id'] }],\n};\n\n/** Collection evolution is additive, so the per-member unique index cannot be narrowed: rows stay and are folded at boot. */\nexport const LEGACY_INTAKE_USER_SETTINGS_SCHEMA: CollectionSchema = {\n name: 'intake_settings',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n config: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'intake_settings_org_user_unique', columns: ['org_id', 'user_id'] }],\n};\n\n/** What the org effectively saw while selections were personal: a member's sources fed the shared board only while their switch was on. */\nexport function mergeIntakeSelections(configs: readonly IntakeConfig[]): IntakeConfig {\n const merged: IntakeConfig = Object.create(null);\n for (const config of configs) {\n for (const [integrationId, selection] of Object.entries(config)) {\n const current = merged[integrationId] ?? { enabled: false, sourceIds: null };\n const syncing = selection.enabled ? (selection.sourceIds ?? []) : [];\n const sourceIds = [...new Set([...(current.sourceIds ?? []), ...syncing])];\n merged[integrationId] = {\n enabled: current.enabled || selection.enabled,\n sourceIds: sourceIds.length ? sourceIds : null,\n };\n }\n }\n return merged;\n}\n\n/**\n * Binds an intake source to the Factory project its items belong to.\n *\n * Intake selections are org-wide, so they cannot say *where* an\n * ingested item should land. GitHub items are naturally scoped by their linked\n * repository; providers without that link (Linear) need this explicit binding\n * so viewing one project's board cannot materialize another project's items.\n */\nexport const INTAKE_SOURCE_BINDINGS_SCHEMA: CollectionSchema = {\n name: 'intake_source_bindings',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n integration_id: { type: 'text' },\n source_id: { type: 'text' },\n factory_project_id: { type: 'text' },\n /** Installed board the source feeds; `null` keeps the legacy source-type routing (issues → work, PRs → review). */\n board: { type: 'text', nullable: true },\n created_by_user_id: { type: 'text', nullable: true },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n indexes: [{ name: 'intake_source_bindings_project_idx', columns: ['org_id', 'factory_project_id'] }],\n uniqueIndexes: [\n {\n name: 'intake_source_bindings_org_integration_source_unique',\n columns: ['org_id', 'integration_id', 'source_id'],\n },\n ],\n};\n\nexport interface IntakeSourceBinding {\n integrationId: string;\n sourceId: string;\n factoryProjectId: string;\n /** Installed board the source feeds, or `null` for legacy source-type routing. */\n board: string | null;\n}\n\n/**\n * Routes items carrying a label to an installed board, per Factory project.\n *\n * Repository-scoped providers (GitHub) already know which project an item\n * belongs to, but one repository can feed several boards: an issue labelled\n * `release` belongs on a release board while the rest stay on Work. Labels\n * without a route fall back to the provider's built-in board.\n */\nexport const INTAKE_LABEL_ROUTES_SCHEMA: CollectionSchema = {\n name: 'intake_label_routes',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n factory_project_id: { type: 'text' },\n integration_id: { type: 'text' },\n /** Label as the provider reports it; matched case-insensitively. */\n label: { type: 'text' },\n board: { type: 'text' },\n created_by_user_id: { type: 'text', nullable: true },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n indexes: [{ name: 'intake_label_routes_project_idx', columns: ['org_id', 'factory_project_id'] }],\n uniqueIndexes: [\n {\n name: 'intake_label_routes_org_project_integration_label_unique',\n columns: ['org_id', 'factory_project_id', 'integration_id', 'label'],\n },\n ],\n};\n\nexport interface IntakeLabelRoute {\n factoryProjectId: string;\n integrationId: string;\n label: string;\n board: string;\n}\n\ntype IntakeLabelRouteRow = {\n factory_project_id: string;\n integration_id: string;\n label: string;\n board: string;\n};\nfunction toIntakeLabelRoute(row: IntakeLabelRouteRow): IntakeLabelRoute {\n return {\n factoryProjectId: row.factory_project_id,\n integrationId: row.integration_id,\n label: row.label,\n board: row.board,\n };\n}\n\n/** Labels are matched the way GitHub treats them: case-insensitively. */\nexport function normalizeIntakeLabel(label: string): string {\n return label.trim().toLowerCase();\n}\n\n/**\n * The board a labelled item should land on under `routes`, or `undefined` when\n * none of its labels is routed. Ties resolve to the first route in `routes`\n * order, so callers should pass a deterministically ordered list.\n */\nexport function resolveIntakeLabelRoute(\n routes: readonly IntakeLabelRoute[],\n labels: readonly string[] | undefined,\n): IntakeLabelRoute | undefined {\n if (!labels?.length) return undefined;\n const normalized = new Set(labels.map(normalizeIntakeLabel));\n return routes.find(route => normalized.has(normalizeIntakeLabel(route.label)));\n}\n\ntype IntakeSourceBindingRow = {\n integration_id: string;\n source_id: string;\n factory_project_id: string;\n board?: string | null;\n};\nfunction toIntakeSourceBinding(row: IntakeSourceBindingRow): IntakeSourceBinding {\n return {\n integrationId: row.integration_id,\n sourceId: row.source_id,\n factoryProjectId: row.factory_project_id,\n board: row.board ?? null,\n };\n}\n\nexport class IntakeStorage extends FactoryStorageDomain {\n constructor() {\n super('intake');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([\n INTAKE_ORG_SETTINGS_SCHEMA,\n LEGACY_INTAKE_USER_SETTINGS_SCHEMA,\n INTAKE_SOURCE_BINDINGS_SCHEMA,\n INTAKE_LABEL_ROUTES_SCHEMA,\n ]);\n await this.#foldLegacyUserSelections();\n }\n\n async #foldLegacyUserSelections(): Promise<void> {\n const legacyRows = await this.ops.findMany<{ org_id: string; config: IntakeConfig }>('intake_settings', {});\n const byOrg = new Map<string, IntakeConfig[]>();\n for (const row of legacyRows) {\n byOrg.set(row.org_id, [...(byOrg.get(row.org_id) ?? []), row.config]);\n }\n for (const [orgId, configs] of byOrg) {\n const folded = await this.ops.findOne('intake_org_settings', { org_id: orgId });\n if (folded) continue;\n await this.#insertConfigIfAbsent(orgId, mergeIntakeSelections(configs));\n }\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('intake_org_settings', {});\n await this.ops.deleteMany('intake_settings', {});\n await this.ops.deleteMany('intake_source_bindings', {});\n await this.ops.deleteMany('intake_label_routes', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async getConfig({\n orgId,\n integrationIds,\n }: {\n orgId: string;\n /**\n * When provided, the result contains exactly these integration ids, with\n * unset integrations defaulting to `{ enabled: true, sourceIds: null }`.\n */\n integrationIds?: string[];\n }): Promise<IntakeConfig> {\n const row = await this.#db.findOne<{ config: IntakeConfig }>('intake_org_settings', { org_id: orgId });\n const saved = structuredClone(row?.config ?? DEFAULT_INTAKE_CONFIG);\n if (!integrationIds) return saved;\n return Object.fromEntries(\n integrationIds.map(integrationId => [integrationId, saved[integrationId] ?? { enabled: true, sourceIds: null }]),\n );\n }\n\n async saveConfig({ orgId, config }: { orgId: string; config: IntakeConfig }): Promise<void> {\n const now = new Date();\n const where = { org_id: orgId };\n const updated = await this.#db.updateMany('intake_org_settings', where, { config, updated_at: now });\n if (updated > 0) return;\n if (await this.#insertConfigIfAbsent(orgId, config)) return;\n await this.#db.updateMany('intake_org_settings', where, { config, updated_at: now });\n }\n\n async #insertConfigIfAbsent(orgId: string, config: IntakeConfig): Promise<boolean> {\n const now = new Date();\n try {\n await this.#db.insertOne('intake_org_settings', { org_id: orgId, config, created_at: now, updated_at: now });\n return true;\n } catch (error) {\n if (error instanceof UniqueViolationError) return false;\n throw error;\n }\n }\n\n /** Every source binding in the org, optionally narrowed to one integration. */\n async listBindings({\n orgId,\n integrationId,\n }: {\n orgId: string;\n integrationId?: string;\n }): Promise<IntakeSourceBinding[]> {\n const rows = await this.#db.findMany<IntakeSourceBindingRow>('intake_source_bindings', {\n org_id: orgId,\n ...(integrationId ? { integration_id: integrationId } : {}),\n });\n return rows.map(toIntakeSourceBinding);\n }\n\n /** Source ids bound to one Factory project. Empty means \"nothing bound\". */\n async listBoundSourceIds({\n orgId,\n integrationId,\n factoryProjectId,\n }: {\n orgId: string;\n integrationId: string;\n factoryProjectId: string;\n }): Promise<string[]> {\n const rows = await this.#db.findMany<IntakeSourceBindingRow>('intake_source_bindings', {\n org_id: orgId,\n integration_id: integrationId,\n factory_project_id: factoryProjectId,\n });\n return rows.map(row => row.source_id);\n }\n\n /** The binding for one source, or `null` when it is unbound. */\n async getBinding({\n orgId,\n integrationId,\n sourceId,\n }: {\n orgId: string;\n integrationId: string;\n sourceId: string;\n }): Promise<IntakeSourceBinding | null> {\n const row = await this.#db.findOne<IntakeSourceBindingRow>('intake_source_bindings', {\n org_id: orgId,\n integration_id: integrationId,\n source_id: sourceId,\n });\n return row ? toIntakeSourceBinding(row) : null;\n }\n\n async clearBinding({\n orgId,\n integrationId,\n sourceId,\n }: {\n orgId: string;\n integrationId: string;\n sourceId: string;\n }): Promise<IntakeSourceBinding | null> {\n const where = { org_id: orgId, integration_id: integrationId, source_id: sourceId };\n return this.storage.withTransaction(\n async ops => {\n const row = await ops.findOne<IntakeSourceBindingRow>('intake_source_bindings', where);\n if (!row) return null;\n await ops.deleteMany('intake_source_bindings', where);\n return toIntakeSourceBinding(row);\n },\n { isolationLevel: 'serializable' },\n );\n }\n\n async setBinding({\n orgId,\n integrationId,\n sourceId,\n factoryProjectId,\n board = null,\n userId,\n }: {\n orgId: string;\n integrationId: string;\n sourceId: string;\n factoryProjectId: string;\n board?: string | null;\n userId?: string;\n }): Promise<void> {\n const where = { org_id: orgId, integration_id: integrationId, source_id: sourceId };\n const now = new Date();\n const patch = { factory_project_id: factoryProjectId, board, updated_at: now };\n const updated = await this.#db.updateMany('intake_source_bindings', where, patch);\n if (updated > 0) return;\n try {\n await this.#db.insertOne('intake_source_bindings', {\n ...where,\n factory_project_id: factoryProjectId,\n board,\n created_by_user_id: userId ?? null,\n created_at: now,\n updated_at: now,\n });\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n await this.#db.updateMany('intake_source_bindings', where, patch);\n }\n }\n /** Atomically replace legacy provider source ids in both selection and routing state. */\n async migrateSourceIds({\n orgId,\n integrationId,\n migrations,\n }: {\n orgId: string;\n integrationId: string;\n migrations: Array<{ from: string; to: string }>;\n }): Promise<{ migrations: Array<{ from: string; to: string }>; conflicts: Array<{ from: string; to: string }> }> {\n if (migrations.length === 0) return { migrations: [], conflicts: [] };\n return this.storage.withTransaction(\n async ops => {\n const bindings = await ops.findMany<IntakeSourceBindingRow>('intake_source_bindings', {\n org_id: orgId,\n integration_id: integrationId,\n });\n const bindingBySource = new Map(bindings.map(binding => [binding.source_id, binding] as const));\n const grouped = new Map<string, Array<{ from: string; to: string }>>();\n for (const migration of migrations) {\n grouped.set(migration.to, [...(grouped.get(migration.to) ?? []), migration]);\n }\n const conflicts: Array<{ from: string; to: string }> = [];\n for (const [to, group] of grouped) {\n const candidates = [bindingBySource.get(to), ...group.map(({ from }) => bindingBySource.get(from))].filter(\n (binding): binding is IntakeSourceBindingRow => binding !== undefined,\n );\n const destinations = new Set(\n candidates.map(binding => `${binding.factory_project_id}\\0${binding.board ?? ''}`),\n );\n if (destinations.size > 1) conflicts.push(...group);\n }\n if (conflicts.length > 0) return { migrations: [], conflicts };\n\n const now = new Date();\n for (const [to, group] of grouped) {\n const canonical = bindingBySource.get(to);\n const legacy = group.flatMap(({ from }) => {\n const binding = bindingBySource.get(from);\n return binding ? [{ from, binding }] : [];\n });\n if (!canonical && legacy.length > 0) {\n const [first, ...duplicates] = legacy;\n await ops.updateMany(\n 'intake_source_bindings',\n { org_id: orgId, integration_id: integrationId, source_id: first!.from },\n { source_id: to, updated_at: now },\n );\n for (const duplicate of duplicates) {\n await ops.deleteMany('intake_source_bindings', {\n org_id: orgId,\n integration_id: integrationId,\n source_id: duplicate.from,\n });\n }\n } else if (canonical) {\n for (const entry of legacy) {\n await ops.deleteMany('intake_source_bindings', {\n org_id: orgId,\n integration_id: integrationId,\n source_id: entry.from,\n });\n }\n }\n }\n\n const configRow = await ops.findOne<{ config: IntakeConfig }>('intake_org_settings', { org_id: orgId });\n if (configRow) {\n const replacements = new Map(migrations.map(({ from, to }) => [from, to] as const));\n const selected = configRow.config[integrationId]?.sourceIds ?? [];\n const nextSelected = [...new Set(selected.map(sourceId => replacements.get(sourceId) ?? sourceId))];\n if (\n nextSelected.length !== selected.length ||\n nextSelected.some((sourceId, index) => sourceId !== selected[index])\n ) {\n const config = structuredClone(configRow.config);\n config[integrationId] = {\n ...(config[integrationId] ?? { enabled: true }),\n sourceIds: nextSelected.length > 0 ? nextSelected : null,\n };\n await ops.updateMany('intake_org_settings', { org_id: orgId }, { config, updated_at: now });\n }\n }\n return { migrations, conflicts: [] };\n },\n { isolationLevel: 'serializable' },\n );\n }\n\n /** Label routes in the org, optionally narrowed to one project and/or integration. Sorted by label. */\n async listLabelRoutes({\n orgId,\n factoryProjectId,\n integrationId,\n }: {\n orgId: string;\n factoryProjectId?: string;\n integrationId?: string;\n }): Promise<IntakeLabelRoute[]> {\n const rows = await this.#db.findMany<IntakeLabelRouteRow>('intake_label_routes', {\n org_id: orgId,\n ...(factoryProjectId ? { factory_project_id: factoryProjectId } : {}),\n ...(integrationId ? { integration_id: integrationId } : {}),\n });\n return rows.map(toIntakeLabelRoute).sort((a, b) => a.label.localeCompare(b.label));\n }\n\n async setLabelRoute({\n orgId,\n factoryProjectId,\n integrationId,\n label,\n board,\n userId,\n }: {\n orgId: string;\n factoryProjectId: string;\n integrationId: string;\n label: string;\n board: string;\n userId?: string;\n }): Promise<void> {\n const where = {\n org_id: orgId,\n factory_project_id: factoryProjectId,\n integration_id: integrationId,\n label: normalizeIntakeLabel(label),\n };\n const now = new Date();\n const patch = { board, updated_at: now };\n const updated = await this.#db.updateMany('intake_label_routes', where, patch);\n if (updated > 0) return;\n try {\n await this.#db.insertOne('intake_label_routes', {\n ...where,\n board,\n created_by_user_id: userId ?? null,\n created_at: now,\n updated_at: now,\n });\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n await this.#db.updateMany('intake_label_routes', where, patch);\n }\n }\n\n /** Remove a label route; returns the route that was removed, or `null` when none existed. */\n async clearLabelRoute({\n orgId,\n factoryProjectId,\n integrationId,\n label,\n }: {\n orgId: string;\n factoryProjectId: string;\n integrationId: string;\n label: string;\n }): Promise<IntakeLabelRoute | null> {\n const where = {\n org_id: orgId,\n factory_project_id: factoryProjectId,\n integration_id: integrationId,\n label: normalizeIntakeLabel(label),\n };\n return this.storage.withTransaction(\n async ops => {\n const row = await ops.findOne<IntakeLabelRouteRow>('intake_label_routes', where);\n if (!row) return null;\n await ops.deleteMany('intake_label_routes', where);\n return toIntakeLabelRoute(row);\n },\n { isolationLevel: 'serializable' },\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"base.js","names":[],"sources":["../../../../src/storage/domains/intake/base.ts"],"sourcesContent":["/**\n * Org-wide intake selections for every configured intake integration.\n *\n * Integration ids are dynamic. Each integration contributes provider-neutral\n * sources through `FactoryIntegration.intake`; this domain only persists which\n * source ids the organization selected. The selection feeds shared boards, so\n * every member reads the same one.\n */\n\nimport { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\nexport interface IntakeSelection {\n enabled: boolean;\n /** Provider-owned source ids; `null` means nothing is selected. */\n sourceIds: string[] | null;\n repositoryByLinearProject?: Record<string, string>;\n}\n\nexport type IntakeConfig = Record<string, IntakeSelection>;\n\nexport const DEFAULT_INTAKE_CONFIG: IntakeConfig = {};\n\nexport const INTAKE_ORG_SETTINGS_SCHEMA: CollectionSchema = {\n name: 'intake_org_settings',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n config: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'intake_org_settings_org_unique', columns: ['org_id'] }],\n};\n\n/** Collection evolution is additive, so the per-member unique index cannot be narrowed: rows stay and are folded at boot. */\nexport const LEGACY_INTAKE_USER_SETTINGS_SCHEMA: CollectionSchema = {\n name: 'intake_settings',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n config: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'intake_settings_org_user_unique', columns: ['org_id', 'user_id'] }],\n};\n\n/** What the org effectively saw while selections were personal: a member's sources fed the shared board only while their switch was on. */\nexport function mergeIntakeSelections(configs: readonly IntakeConfig[]): IntakeConfig {\n const merged: IntakeConfig = Object.create(null);\n for (const config of configs) {\n for (const [integrationId, selection] of Object.entries(config)) {\n const current = merged[integrationId] ?? { enabled: false, sourceIds: null };\n const syncing = selection.enabled ? (selection.sourceIds ?? []) : [];\n const sourceIds = [...new Set([...(current.sourceIds ?? []), ...syncing])];\n merged[integrationId] = {\n enabled: current.enabled || selection.enabled,\n sourceIds: sourceIds.length ? sourceIds : null,\n };\n }\n }\n return merged;\n}\n\n/**\n * Binds an intake source to the Factory project its items belong to.\n *\n * Intake selections are org-wide, so they cannot say *where* an\n * ingested item should land. GitHub items are naturally scoped by their linked\n * repository; providers without that link (Linear) need this explicit binding\n * so viewing one project's board cannot materialize another project's items.\n */\nexport const INTAKE_SOURCE_BINDINGS_SCHEMA: CollectionSchema = {\n name: 'intake_source_bindings',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n integration_id: { type: 'text' },\n source_id: { type: 'text' },\n factory_project_id: { type: 'text' },\n /** Installed board the source feeds; `null` keeps the legacy source-type routing (issues → work, PRs → review). */\n board: { type: 'text', nullable: true },\n created_by_user_id: { type: 'text', nullable: true },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n indexes: [{ name: 'intake_source_bindings_project_idx', columns: ['org_id', 'factory_project_id'] }],\n uniqueIndexes: [\n {\n name: 'intake_source_bindings_org_integration_source_unique',\n columns: ['org_id', 'integration_id', 'source_id'],\n },\n ],\n};\n\nexport interface IntakeSourceBinding {\n integrationId: string;\n sourceId: string;\n factoryProjectId: string;\n /** Installed board the source feeds, or `null` for legacy source-type routing. */\n board: string | null;\n}\n\n/**\n * Routes items carrying a label to an installed board, per Factory project.\n *\n * Repository-scoped providers (GitHub) already know which project an item\n * belongs to, but one repository can feed several boards: an issue labelled\n * `release` belongs on a release board while the rest stay on Work. Labels\n * without a route fall back to the provider's built-in board.\n */\nexport const INTAKE_LABEL_ROUTES_SCHEMA: CollectionSchema = {\n name: 'intake_label_routes',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n factory_project_id: { type: 'text' },\n integration_id: { type: 'text' },\n /** Label as the provider reports it; matched case-insensitively. */\n label: { type: 'text' },\n board: { type: 'text' },\n created_by_user_id: { type: 'text', nullable: true },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n indexes: [{ name: 'intake_label_routes_project_idx', columns: ['org_id', 'factory_project_id'] }],\n uniqueIndexes: [\n {\n name: 'intake_label_routes_org_project_integration_label_unique',\n columns: ['org_id', 'factory_project_id', 'integration_id', 'label'],\n },\n ],\n};\n\nexport interface IntakeLabelRoute {\n factoryProjectId: string;\n integrationId: string;\n label: string;\n board: string;\n}\n\ntype IntakeLabelRouteRow = {\n factory_project_id: string;\n integration_id: string;\n label: string;\n board: string;\n};\nfunction toIntakeLabelRoute(row: IntakeLabelRouteRow): IntakeLabelRoute {\n return {\n factoryProjectId: row.factory_project_id,\n integrationId: row.integration_id,\n label: row.label,\n board: row.board,\n };\n}\n\n/** Labels are matched the way GitHub treats them: case-insensitively. */\nexport function normalizeIntakeLabel(label: string): string {\n return label.trim().toLowerCase();\n}\n\n/**\n * The board a labelled item should land on under `routes`, or `undefined` when\n * none of its labels is routed. Ties resolve to the first route in `routes`\n * order, so callers should pass a deterministically ordered list.\n */\nexport function resolveIntakeLabelRoute(\n routes: readonly IntakeLabelRoute[],\n labels: readonly string[] | undefined,\n): IntakeLabelRoute | undefined {\n if (!labels?.length) return undefined;\n const normalized = new Set(labels.map(normalizeIntakeLabel));\n return routes.find(route => normalized.has(normalizeIntakeLabel(route.label)));\n}\n\ntype IntakeSourceBindingRow = {\n integration_id: string;\n source_id: string;\n factory_project_id: string;\n board?: string | null;\n};\nfunction toIntakeSourceBinding(row: IntakeSourceBindingRow): IntakeSourceBinding {\n return {\n integrationId: row.integration_id,\n sourceId: row.source_id,\n factoryProjectId: row.factory_project_id,\n board: row.board ?? null,\n };\n}\n\nexport class IntakeStorage extends FactoryStorageDomain {\n constructor() {\n super('intake');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([\n INTAKE_ORG_SETTINGS_SCHEMA,\n LEGACY_INTAKE_USER_SETTINGS_SCHEMA,\n INTAKE_SOURCE_BINDINGS_SCHEMA,\n INTAKE_LABEL_ROUTES_SCHEMA,\n ]);\n await this.#foldLegacyUserSelections();\n }\n\n async #foldLegacyUserSelections(): Promise<void> {\n const legacyRows = await this.ops.findMany<{ org_id: string; config: IntakeConfig }>('intake_settings', {});\n const byOrg = new Map<string, IntakeConfig[]>();\n for (const row of legacyRows) {\n byOrg.set(row.org_id, [...(byOrg.get(row.org_id) ?? []), row.config]);\n }\n for (const [orgId, configs] of byOrg) {\n const folded = await this.ops.findOne('intake_org_settings', { org_id: orgId });\n if (folded) continue;\n await this.#insertConfigIfAbsent(orgId, mergeIntakeSelections(configs));\n }\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('intake_org_settings', {});\n await this.ops.deleteMany('intake_settings', {});\n await this.ops.deleteMany('intake_source_bindings', {});\n await this.ops.deleteMany('intake_label_routes', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async getConfig({\n orgId,\n integrationIds,\n }: {\n orgId: string;\n /**\n * When provided, the result contains exactly these integration ids, with\n * unset integrations defaulting to `{ enabled: true, sourceIds: null }`.\n */\n integrationIds?: string[];\n }): Promise<IntakeConfig> {\n const row = await this.#db.findOne<{ config: IntakeConfig }>('intake_org_settings', { org_id: orgId });\n const saved = structuredClone(row?.config ?? DEFAULT_INTAKE_CONFIG);\n if (!integrationIds) return saved;\n return Object.fromEntries(\n integrationIds.map(integrationId => [integrationId, saved[integrationId] ?? { enabled: true, sourceIds: null }]),\n );\n }\n\n async saveConfig({ orgId, config }: { orgId: string; config: IntakeConfig }): Promise<void> {\n const now = new Date();\n const where = { org_id: orgId };\n const updated = await this.#db.updateMany('intake_org_settings', where, { config, updated_at: now });\n if (updated > 0) return;\n if (await this.#insertConfigIfAbsent(orgId, config)) return;\n await this.#db.updateMany('intake_org_settings', where, { config, updated_at: now });\n }\n\n /** Overlay `config` onto the stored selections; integrations it omits keep their stored value. */\n async mergeConfig({ orgId, config }: { orgId: string; config: IntakeConfig }): Promise<IntakeConfig> {\n const merged: IntakeConfig = Object.assign(Object.create(null), await this.getConfig({ orgId }), config);\n await this.saveConfig({ orgId, config: merged });\n return merged;\n }\n\n async #insertConfigIfAbsent(orgId: string, config: IntakeConfig): Promise<boolean> {\n const now = new Date();\n try {\n await this.#db.insertOne('intake_org_settings', { org_id: orgId, config, created_at: now, updated_at: now });\n return true;\n } catch (error) {\n if (error instanceof UniqueViolationError) return false;\n throw error;\n }\n }\n\n /** Every source binding in the org, optionally narrowed to one integration. */\n async listBindings({\n orgId,\n integrationId,\n }: {\n orgId: string;\n integrationId?: string;\n }): Promise<IntakeSourceBinding[]> {\n const rows = await this.#db.findMany<IntakeSourceBindingRow>('intake_source_bindings', {\n org_id: orgId,\n ...(integrationId ? { integration_id: integrationId } : {}),\n });\n return rows.map(toIntakeSourceBinding);\n }\n\n /** Source ids bound to one Factory project. Empty means \"nothing bound\". */\n async listBoundSourceIds({\n orgId,\n integrationId,\n factoryProjectId,\n }: {\n orgId: string;\n integrationId: string;\n factoryProjectId: string;\n }): Promise<string[]> {\n const rows = await this.#db.findMany<IntakeSourceBindingRow>('intake_source_bindings', {\n org_id: orgId,\n integration_id: integrationId,\n factory_project_id: factoryProjectId,\n });\n return rows.map(row => row.source_id);\n }\n\n /** The binding for one source, or `null` when it is unbound. */\n async getBinding({\n orgId,\n integrationId,\n sourceId,\n }: {\n orgId: string;\n integrationId: string;\n sourceId: string;\n }): Promise<IntakeSourceBinding | null> {\n const row = await this.#db.findOne<IntakeSourceBindingRow>('intake_source_bindings', {\n org_id: orgId,\n integration_id: integrationId,\n source_id: sourceId,\n });\n return row ? toIntakeSourceBinding(row) : null;\n }\n\n async clearBinding({\n orgId,\n integrationId,\n sourceId,\n }: {\n orgId: string;\n integrationId: string;\n sourceId: string;\n }): Promise<IntakeSourceBinding | null> {\n const where = { org_id: orgId, integration_id: integrationId, source_id: sourceId };\n return this.storage.withTransaction(\n async ops => {\n const row = await ops.findOne<IntakeSourceBindingRow>('intake_source_bindings', where);\n if (!row) return null;\n await ops.deleteMany('intake_source_bindings', where);\n return toIntakeSourceBinding(row);\n },\n { isolationLevel: 'serializable' },\n );\n }\n\n async setBinding({\n orgId,\n integrationId,\n sourceId,\n factoryProjectId,\n board = null,\n userId,\n }: {\n orgId: string;\n integrationId: string;\n sourceId: string;\n factoryProjectId: string;\n board?: string | null;\n userId?: string;\n }): Promise<void> {\n const where = { org_id: orgId, integration_id: integrationId, source_id: sourceId };\n const now = new Date();\n const patch = { factory_project_id: factoryProjectId, board, updated_at: now };\n const updated = await this.#db.updateMany('intake_source_bindings', where, patch);\n if (updated > 0) return;\n try {\n await this.#db.insertOne('intake_source_bindings', {\n ...where,\n factory_project_id: factoryProjectId,\n board,\n created_by_user_id: userId ?? null,\n created_at: now,\n updated_at: now,\n });\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n await this.#db.updateMany('intake_source_bindings', where, patch);\n }\n }\n /** Atomically replace legacy provider source ids in both selection and routing state. */\n async migrateSourceIds({\n orgId,\n integrationId,\n migrations,\n }: {\n orgId: string;\n integrationId: string;\n migrations: Array<{ from: string; to: string }>;\n }): Promise<{ migrations: Array<{ from: string; to: string }>; conflicts: Array<{ from: string; to: string }> }> {\n if (migrations.length === 0) return { migrations: [], conflicts: [] };\n return this.storage.withTransaction(\n async ops => {\n const bindings = await ops.findMany<IntakeSourceBindingRow>('intake_source_bindings', {\n org_id: orgId,\n integration_id: integrationId,\n });\n const bindingBySource = new Map(bindings.map(binding => [binding.source_id, binding] as const));\n const grouped = new Map<string, Array<{ from: string; to: string }>>();\n for (const migration of migrations) {\n grouped.set(migration.to, [...(grouped.get(migration.to) ?? []), migration]);\n }\n const conflicts: Array<{ from: string; to: string }> = [];\n for (const [to, group] of grouped) {\n const candidates = [bindingBySource.get(to), ...group.map(({ from }) => bindingBySource.get(from))].filter(\n (binding): binding is IntakeSourceBindingRow => binding !== undefined,\n );\n const destinations = new Set(\n candidates.map(binding => `${binding.factory_project_id}\\0${binding.board ?? ''}`),\n );\n if (destinations.size > 1) conflicts.push(...group);\n }\n if (conflicts.length > 0) return { migrations: [], conflicts };\n\n const now = new Date();\n for (const [to, group] of grouped) {\n const canonical = bindingBySource.get(to);\n const legacy = group.flatMap(({ from }) => {\n const binding = bindingBySource.get(from);\n return binding ? [{ from, binding }] : [];\n });\n if (!canonical && legacy.length > 0) {\n const [first, ...duplicates] = legacy;\n await ops.updateMany(\n 'intake_source_bindings',\n { org_id: orgId, integration_id: integrationId, source_id: first!.from },\n { source_id: to, updated_at: now },\n );\n for (const duplicate of duplicates) {\n await ops.deleteMany('intake_source_bindings', {\n org_id: orgId,\n integration_id: integrationId,\n source_id: duplicate.from,\n });\n }\n } else if (canonical) {\n for (const entry of legacy) {\n await ops.deleteMany('intake_source_bindings', {\n org_id: orgId,\n integration_id: integrationId,\n source_id: entry.from,\n });\n }\n }\n }\n\n const configRow = await ops.findOne<{ config: IntakeConfig }>('intake_org_settings', { org_id: orgId });\n if (configRow) {\n const replacements = new Map(migrations.map(({ from, to }) => [from, to] as const));\n const selected = configRow.config[integrationId]?.sourceIds ?? [];\n const nextSelected = [...new Set(selected.map(sourceId => replacements.get(sourceId) ?? sourceId))];\n if (\n nextSelected.length !== selected.length ||\n nextSelected.some((sourceId, index) => sourceId !== selected[index])\n ) {\n const config = structuredClone(configRow.config);\n config[integrationId] = {\n ...(config[integrationId] ?? { enabled: true }),\n sourceIds: nextSelected.length > 0 ? nextSelected : null,\n };\n await ops.updateMany('intake_org_settings', { org_id: orgId }, { config, updated_at: now });\n }\n }\n return { migrations, conflicts: [] };\n },\n { isolationLevel: 'serializable' },\n );\n }\n\n /** Label routes in the org, optionally narrowed to one project and/or integration. Sorted by label. */\n async listLabelRoutes({\n orgId,\n factoryProjectId,\n integrationId,\n }: {\n orgId: string;\n factoryProjectId?: string;\n integrationId?: string;\n }): Promise<IntakeLabelRoute[]> {\n const rows = await this.#db.findMany<IntakeLabelRouteRow>('intake_label_routes', {\n org_id: orgId,\n ...(factoryProjectId ? { factory_project_id: factoryProjectId } : {}),\n ...(integrationId ? { integration_id: integrationId } : {}),\n });\n return rows.map(toIntakeLabelRoute).sort((a, b) => a.label.localeCompare(b.label));\n }\n\n async setLabelRoute({\n orgId,\n factoryProjectId,\n integrationId,\n label,\n board,\n userId,\n }: {\n orgId: string;\n factoryProjectId: string;\n integrationId: string;\n label: string;\n board: string;\n userId?: string;\n }): Promise<void> {\n const where = {\n org_id: orgId,\n factory_project_id: factoryProjectId,\n integration_id: integrationId,\n label: normalizeIntakeLabel(label),\n };\n const now = new Date();\n const patch = { board, updated_at: now };\n const updated = await this.#db.updateMany('intake_label_routes', where, patch);\n if (updated > 0) return;\n try {\n await this.#db.insertOne('intake_label_routes', {\n ...where,\n board,\n created_by_user_id: userId ?? null,\n created_at: now,\n updated_at: now,\n });\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n await this.#db.updateMany('intake_label_routes', where, patch);\n }\n }\n\n /** Remove a label route; returns the route that was removed, or `null` when none existed. */\n async clearLabelRoute({\n orgId,\n factoryProjectId,\n integrationId,\n label,\n }: {\n orgId: string;\n factoryProjectId: string;\n integrationId: string;\n label: string;\n }): Promise<IntakeLabelRoute | null> {\n const where = {\n org_id: orgId,\n factory_project_id: factoryProjectId,\n integration_id: integrationId,\n label: normalizeIntakeLabel(label),\n };\n return this.storage.withTransaction(\n async ops => {\n const row = await ops.findOne<IntakeLabelRouteRow>('intake_label_routes', where);\n if (!row) return null;\n await ops.deleteMany('intake_label_routes', where);\n return toIntakeLabelRoute(row);\n },\n { isolationLevel: 'serializable' },\n );\n }\n}\n"],"mappings":";;;;;;;;;;AAqBA,MAAa,wBAAsC,CAAC;AAEpD,MAAa,6BAA+C;CAC1D,MAAM;CACN,SAAS;EACP,IAAI,EAAE,MAAM,UAAU;EACtB,QAAQ,EAAE,MAAM,OAAO;EACvB,QAAQ,EAAE,MAAM,OAAO;EACvB,YAAY,EAAE,MAAM,YAAY;EAChC,YAAY,EAAE,MAAM,YAAY;CAClC;CACA,eAAe,CAAC;EAAE,MAAM;EAAkC,SAAS,CAAC,QAAQ;CAAE,CAAC;AACjF;;AAGA,MAAa,qCAAuD;CAClE,MAAM;CACN,SAAS;EACP,IAAI,EAAE,MAAM,UAAU;EACtB,QAAQ,EAAE,MAAM,OAAO;EACvB,SAAS,EAAE,MAAM,OAAO;EACxB,QAAQ,EAAE,MAAM,OAAO;EACvB,YAAY,EAAE,MAAM,YAAY;EAChC,YAAY,EAAE,MAAM,YAAY;CAClC;CACA,eAAe,CAAC;EAAE,MAAM;EAAmC,SAAS,CAAC,UAAU,SAAS;CAAE,CAAC;AAC7F;;AAGA,SAAgB,sBAAsB,SAAgD;CACpF,MAAM,SAAuB,OAAO,OAAO,IAAI;CAC/C,KAAK,MAAM,UAAU,SACnB,KAAK,MAAM,CAAC,eAAe,cAAc,OAAO,QAAQ,MAAM,GAAG;EAC/D,MAAM,UAAU,OAAO,kBAAkB;GAAE,SAAS;GAAO,WAAW;EAAK;EAC3E,MAAM,UAAU,UAAU,UAAW,UAAU,aAAa,CAAC,IAAK,CAAC;EACnE,MAAM,YAAY,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAI,QAAQ,aAAa,CAAC,GAAI,GAAG,OAAO,CAAC,CAAC;EACzE,OAAO,iBAAiB;GACtB,SAAS,QAAQ,WAAW,UAAU;GACtC,WAAW,UAAU,SAAS,YAAY;EAC5C;CACF;CAEF,OAAO;AACT;;;;;;;;;AAUA,MAAa,gCAAkD;CAC7D,MAAM;CACN,SAAS;EACP,IAAI,EAAE,MAAM,UAAU;EACtB,QAAQ,EAAE,MAAM,OAAO;EACvB,gBAAgB,EAAE,MAAM,OAAO;EAC/B,WAAW,EAAE,MAAM,OAAO;EAC1B,oBAAoB,EAAE,MAAM,OAAO;;EAEnC,OAAO;GAAE,MAAM;GAAQ,UAAU;EAAK;EACtC,oBAAoB;GAAE,MAAM;GAAQ,UAAU;EAAK;EACnD,YAAY,EAAE,MAAM,YAAY;EAChC,YAAY,EAAE,MAAM,YAAY;CAClC;CACA,SAAS,CAAC;EAAE,MAAM;EAAsC,SAAS,CAAC,UAAU,oBAAoB;CAAE,CAAC;CACnG,eAAe,CACb;EACE,MAAM;EACN,SAAS;GAAC;GAAU;GAAkB;EAAW;CACnD,CACF;AACF;;;;;;;;;AAkBA,MAAa,6BAA+C;CAC1D,MAAM;CACN,SAAS;EACP,IAAI,EAAE,MAAM,UAAU;EACtB,QAAQ,EAAE,MAAM,OAAO;EACvB,oBAAoB,EAAE,MAAM,OAAO;EACnC,gBAAgB,EAAE,MAAM,OAAO;;EAE/B,OAAO,EAAE,MAAM,OAAO;EACtB,OAAO,EAAE,MAAM,OAAO;EACtB,oBAAoB;GAAE,MAAM;GAAQ,UAAU;EAAK;EACnD,YAAY,EAAE,MAAM,YAAY;EAChC,YAAY,EAAE,MAAM,YAAY;CAClC;CACA,SAAS,CAAC;EAAE,MAAM;EAAmC,SAAS,CAAC,UAAU,oBAAoB;CAAE,CAAC;CAChG,eAAe,CACb;EACE,MAAM;EACN,SAAS;GAAC;GAAU;GAAsB;GAAkB;EAAO;CACrE,CACF;AACF;AAeA,SAAS,mBAAmB,KAA4C;CACtE,OAAO;EACL,kBAAkB,IAAI;EACtB,eAAe,IAAI;EACnB,OAAO,IAAI;EACX,OAAO,IAAI;CACb;AACF;;AAGA,SAAgB,qBAAqB,OAAuB;CAC1D,OAAO,MAAM,KAAK,CAAC,CAAC,YAAY;AAClC;;;;;;AAOA,SAAgB,wBACd,QACA,QAC8B;CAC9B,IAAI,CAAC,QAAQ,QAAQ,OAAO,KAAA;CAC5B,MAAM,aAAa,IAAI,IAAI,OAAO,IAAI,oBAAoB,CAAC;CAC3D,OAAO,OAAO,MAAK,UAAS,WAAW,IAAI,qBAAqB,MAAM,KAAK,CAAC,CAAC;AAC/E;AAQA,SAAS,sBAAsB,KAAkD;CAC/E,OAAO;EACL,eAAe,IAAI;EACnB,UAAU,IAAI;EACd,kBAAkB,IAAI;EACtB,OAAO,IAAI,SAAS;CACtB;AACF;AAEA,IAAa,gBAAb,cAAmC,qBAAqB;CACtD,cAAc;EACZ,MAAM,QAAQ;CAChB;CAEA,MAAM,OAAsB;EAC1B,MAAM,KAAK,kBAAkB;GAC3B;GACA;GACA;GACA;EACF,CAAC;EACD,MAAM,KAAK,0BAA0B;CACvC;CAEA,MAAM,4BAA2C;EAC/C,MAAM,aAAa,MAAM,KAAK,IAAI,SAAmD,mBAAmB,CAAC,CAAC;EAC1G,MAAM,wBAAQ,IAAI,IAA4B;EAC9C,KAAK,MAAM,OAAO,YAChB,MAAM,IAAI,IAAI,QAAQ,CAAC,GAAI,MAAM,IAAI,IAAI,MAAM,KAAK,CAAC,GAAI,IAAI,MAAM,CAAC;EAEtE,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO;GAEpC,IAAI,MADiB,KAAK,IAAI,QAAQ,uBAAuB,EAAE,QAAQ,MAAM,CAAC,GAClE;GACZ,MAAM,KAAK,sBAAsB,OAAO,sBAAsB,OAAO,CAAC;EACxE;CACF;CAEA,MAAM,sBAAqC;EACzC,MAAM,KAAK,IAAI,WAAW,uBAAuB,CAAC,CAAC;EACnD,MAAM,KAAK,IAAI,WAAW,mBAAmB,CAAC,CAAC;EAC/C,MAAM,KAAK,IAAI,WAAW,0BAA0B,CAAC,CAAC;EACtD,MAAM,KAAK,IAAI,WAAW,uBAAuB,CAAC,CAAC;CACrD;CAEA,IAAI,MAAyB;EAC3B,OAAO,KAAK;CACd;CAEA,MAAM,UAAU,EACd,OACA,kBAQwB;EACxB,MAAM,MAAM,MAAM,KAAK,IAAI,QAAkC,uBAAuB,EAAE,QAAQ,MAAM,CAAC;EACrG,MAAM,QAAQ,gBAAgB,KAAK,UAAU,qBAAqB;EAClE,IAAI,CAAC,gBAAgB,OAAO;EAC5B,OAAO,OAAO,YACZ,eAAe,KAAI,kBAAiB,CAAC,eAAe,MAAM,kBAAkB;GAAE,SAAS;GAAM,WAAW;EAAK,CAAC,CAAC,CACjH;CACF;CAEA,MAAM,WAAW,EAAE,OAAO,UAAkE;EAC1F,MAAM,sBAAM,IAAI,KAAK;EACrB,MAAM,QAAQ,EAAE,QAAQ,MAAM;EAE9B,IAAI,MADkB,KAAK,IAAI,WAAW,uBAAuB,OAAO;GAAE;GAAQ,YAAY;EAAI,CAAC,IACrF,GAAG;EACjB,IAAI,MAAM,KAAK,sBAAsB,OAAO,MAAM,GAAG;EACrD,MAAM,KAAK,IAAI,WAAW,uBAAuB,OAAO;GAAE;GAAQ,YAAY;EAAI,CAAC;CACrF;;CAGA,MAAM,YAAY,EAAE,OAAO,UAA0E;EACnG,MAAM,SAAuB,OAAO,OAAO,OAAO,OAAO,IAAI,GAAG,MAAM,KAAK,UAAU,EAAE,MAAM,CAAC,GAAG,MAAM;EACvG,MAAM,KAAK,WAAW;GAAE;GAAO,QAAQ;EAAO,CAAC;EAC/C,OAAO;CACT;CAEA,MAAM,sBAAsB,OAAe,QAAwC;EACjF,MAAM,sBAAM,IAAI,KAAK;EACrB,IAAI;GACF,MAAM,KAAK,IAAI,UAAU,uBAAuB;IAAE,QAAQ;IAAO;IAAQ,YAAY;IAAK,YAAY;GAAI,CAAC;GAC3G,OAAO;EACT,SAAS,OAAO;GACd,IAAI,iBAAiB,sBAAsB,OAAO;GAClD,MAAM;EACR;CACF;;CAGA,MAAM,aAAa,EACjB,OACA,iBAIiC;EAKjC,QAAO,MAJY,KAAK,IAAI,SAAiC,0BAA0B;GACrF,QAAQ;GACR,GAAI,gBAAgB,EAAE,gBAAgB,cAAc,IAAI,CAAC;EAC3D,CAAC,EAAA,CACW,IAAI,qBAAqB;CACvC;;CAGA,MAAM,mBAAmB,EACvB,OACA,eACA,oBAKoB;EAMpB,QAAO,MALY,KAAK,IAAI,SAAiC,0BAA0B;GACrF,QAAQ;GACR,gBAAgB;GAChB,oBAAoB;EACtB,CAAC,EAAA,CACW,KAAI,QAAO,IAAI,SAAS;CACtC;;CAGA,MAAM,WAAW,EACf,OACA,eACA,YAKsC;EACtC,MAAM,MAAM,MAAM,KAAK,IAAI,QAAgC,0BAA0B;GACnF,QAAQ;GACR,gBAAgB;GAChB,WAAW;EACb,CAAC;EACD,OAAO,MAAM,sBAAsB,GAAG,IAAI;CAC5C;CAEA,MAAM,aAAa,EACjB,OACA,eACA,YAKsC;EACtC,MAAM,QAAQ;GAAE,QAAQ;GAAO,gBAAgB;GAAe,WAAW;EAAS;EAClF,OAAO,KAAK,QAAQ,gBAClB,OAAM,QAAO;GACX,MAAM,MAAM,MAAM,IAAI,QAAgC,0BAA0B,KAAK;GACrF,IAAI,CAAC,KAAK,OAAO;GACjB,MAAM,IAAI,WAAW,0BAA0B,KAAK;GACpD,OAAO,sBAAsB,GAAG;EAClC,GACA,EAAE,gBAAgB,eAAe,CACnC;CACF;CAEA,MAAM,WAAW,EACf,OACA,eACA,UACA,kBACA,QAAQ,MACR,UAQgB;EAChB,MAAM,QAAQ;GAAE,QAAQ;GAAO,gBAAgB;GAAe,WAAW;EAAS;EAClF,MAAM,sBAAM,IAAI,KAAK;EACrB,MAAM,QAAQ;GAAE,oBAAoB;GAAkB;GAAO,YAAY;EAAI;EAE7E,IAAI,MADkB,KAAK,IAAI,WAAW,0BAA0B,OAAO,KAAK,IAClE,GAAG;EACjB,IAAI;GACF,MAAM,KAAK,IAAI,UAAU,0BAA0B;IACjD,GAAG;IACH,oBAAoB;IACpB;IACA,oBAAoB,UAAU;IAC9B,YAAY;IACZ,YAAY;GACd,CAAC;EACH,SAAS,OAAO;GACd,IAAI,EAAE,iBAAiB,uBAAuB,MAAM;GACpD,MAAM,KAAK,IAAI,WAAW,0BAA0B,OAAO,KAAK;EAClE;CACF;;CAEA,MAAM,iBAAiB,EACrB,OACA,eACA,cAK+G;EAC/G,IAAI,WAAW,WAAW,GAAG,OAAO;GAAE,YAAY,CAAC;GAAG,WAAW,CAAC;EAAE;EACpE,OAAO,KAAK,QAAQ,gBAClB,OAAM,QAAO;GACX,MAAM,WAAW,MAAM,IAAI,SAAiC,0BAA0B;IACpF,QAAQ;IACR,gBAAgB;GAClB,CAAC;GACD,MAAM,kBAAkB,IAAI,IAAI,SAAS,KAAI,YAAW,CAAC,QAAQ,WAAW,OAAO,CAAU,CAAC;GAC9F,MAAM,0BAAU,IAAI,IAAiD;GACrE,KAAK,MAAM,aAAa,YACtB,QAAQ,IAAI,UAAU,IAAI,CAAC,GAAI,QAAQ,IAAI,UAAU,EAAE,KAAK,CAAC,GAAI,SAAS,CAAC;GAE7E,MAAM,YAAiD,CAAC;GACxD,KAAK,MAAM,CAAC,IAAI,UAAU,SAAS;IACjC,MAAM,aAAa,CAAC,gBAAgB,IAAI,EAAE,GAAG,GAAG,MAAM,KAAK,EAAE,WAAW,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,QACjG,YAA+C,YAAY,KAAA,CAC9D;IAIA,IAAI,IAHqB,IACvB,WAAW,KAAI,YAAW,GAAG,QAAQ,mBAAmB,IAAI,QAAQ,SAAS,IAAI,CAEpE,CAAC,CAAC,OAAO,GAAG,UAAU,KAAK,GAAG,KAAK;GACpD;GACA,IAAI,UAAU,SAAS,GAAG,OAAO;IAAE,YAAY,CAAC;IAAG;GAAU;GAE7D,MAAM,sBAAM,IAAI,KAAK;GACrB,KAAK,MAAM,CAAC,IAAI,UAAU,SAAS;IACjC,MAAM,YAAY,gBAAgB,IAAI,EAAE;IACxC,MAAM,SAAS,MAAM,SAAS,EAAE,WAAW;KACzC,MAAM,UAAU,gBAAgB,IAAI,IAAI;KACxC,OAAO,UAAU,CAAC;MAAE;MAAM;KAAQ,CAAC,IAAI,CAAC;IAC1C,CAAC;IACD,IAAI,CAAC,aAAa,OAAO,SAAS,GAAG;KACnC,MAAM,CAAC,OAAO,GAAG,cAAc;KAC/B,MAAM,IAAI,WACR,0BACA;MAAE,QAAQ;MAAO,gBAAgB;MAAe,WAAW,MAAO;KAAK,GACvE;MAAE,WAAW;MAAI,YAAY;KAAI,CACnC;KACA,KAAK,MAAM,aAAa,YACtB,MAAM,IAAI,WAAW,0BAA0B;MAC7C,QAAQ;MACR,gBAAgB;MAChB,WAAW,UAAU;KACvB,CAAC;IAEL,OAAO,IAAI,WACT,KAAK,MAAM,SAAS,QAClB,MAAM,IAAI,WAAW,0BAA0B;KAC7C,QAAQ;KACR,gBAAgB;KAChB,WAAW,MAAM;IACnB,CAAC;GAGP;GAEA,MAAM,YAAY,MAAM,IAAI,QAAkC,uBAAuB,EAAE,QAAQ,MAAM,CAAC;GACtG,IAAI,WAAW;IACb,MAAM,eAAe,IAAI,IAAI,WAAW,KAAK,EAAE,MAAM,SAAS,CAAC,MAAM,EAAE,CAAU,CAAC;IAClF,MAAM,WAAW,UAAU,OAAO,cAAc,EAAE,aAAa,CAAC;IAChE,MAAM,eAAe,CAAC,GAAG,IAAI,IAAI,SAAS,KAAI,aAAY,aAAa,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC;IAClG,IACE,aAAa,WAAW,SAAS,UACjC,aAAa,MAAM,UAAU,UAAU,aAAa,SAAS,MAAM,GACnE;KACA,MAAM,SAAS,gBAAgB,UAAU,MAAM;KAC/C,OAAO,iBAAiB;MACtB,GAAI,OAAO,kBAAkB,EAAE,SAAS,KAAK;MAC7C,WAAW,aAAa,SAAS,IAAI,eAAe;KACtD;KACA,MAAM,IAAI,WAAW,uBAAuB,EAAE,QAAQ,MAAM,GAAG;MAAE;MAAQ,YAAY;KAAI,CAAC;IAC5F;GACF;GACA,OAAO;IAAE;IAAY,WAAW,CAAC;GAAE;EACrC,GACA,EAAE,gBAAgB,eAAe,CACnC;CACF;;CAGA,MAAM,gBAAgB,EACpB,OACA,kBACA,iBAK8B;EAM9B,QAAO,MALY,KAAK,IAAI,SAA8B,uBAAuB;GAC/E,QAAQ;GACR,GAAI,mBAAmB,EAAE,oBAAoB,iBAAiB,IAAI,CAAC;GACnE,GAAI,gBAAgB,EAAE,gBAAgB,cAAc,IAAI,CAAC;EAC3D,CAAC,EAAA,CACW,IAAI,kBAAkB,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,KAAK,CAAC;CACnF;CAEA,MAAM,cAAc,EAClB,OACA,kBACA,eACA,OACA,OACA,UAQgB;EAChB,MAAM,QAAQ;GACZ,QAAQ;GACR,oBAAoB;GACpB,gBAAgB;GAChB,OAAO,qBAAqB,KAAK;EACnC;EACA,MAAM,sBAAM,IAAI,KAAK;EACrB,MAAM,QAAQ;GAAE;GAAO,YAAY;EAAI;EAEvC,IAAI,MADkB,KAAK,IAAI,WAAW,uBAAuB,OAAO,KAAK,IAC/D,GAAG;EACjB,IAAI;GACF,MAAM,KAAK,IAAI,UAAU,uBAAuB;IAC9C,GAAG;IACH;IACA,oBAAoB,UAAU;IAC9B,YAAY;IACZ,YAAY;GACd,CAAC;EACH,SAAS,OAAO;GACd,IAAI,EAAE,iBAAiB,uBAAuB,MAAM;GACpD,MAAM,KAAK,IAAI,WAAW,uBAAuB,OAAO,KAAK;EAC/D;CACF;;CAGA,MAAM,gBAAgB,EACpB,OACA,kBACA,eACA,SAMmC;EACnC,MAAM,QAAQ;GACZ,QAAQ;GACR,oBAAoB;GACpB,gBAAgB;GAChB,OAAO,qBAAqB,KAAK;EACnC;EACA,OAAO,KAAK,QAAQ,gBAClB,OAAM,QAAO;GACX,MAAM,MAAM,MAAM,IAAI,QAA6B,uBAAuB,KAAK;GAC/E,IAAI,CAAC,KAAK,OAAO;GACjB,MAAM,IAAI,WAAW,uBAAuB,KAAK;GACjD,OAAO,mBAAmB,GAAG;EAC/B,GACA,EAAE,gBAAgB,eAAe,CACnC;CACF;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createPlaintextFactorySecretEncryption } from "../../../secret-encryption.js";
|
|
2
2
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
3
|
-
|
|
3
|
+
// src/storage/domains/integrations/base.ts
|
|
4
4
|
/**
|
|
5
5
|
* Generic integration storage — the default persistence surface for
|
|
6
6
|
* `FactoryIntegration`s.
|
|
@@ -334,7 +334,6 @@ var IntegrationStorage = class extends FactoryStorageDomain {
|
|
|
334
334
|
};
|
|
335
335
|
}
|
|
336
336
|
};
|
|
337
|
-
//#endregion
|
|
338
337
|
export { INTEGRATION_CONNECTIONS_SCHEMA, INTEGRATION_SETTINGS_SCHEMA, INTEGRATION_SUBSCRIPTIONS_SCHEMA, IntegrationStorage };
|
|
339
338
|
|
|
340
339
|
//# sourceMappingURL=base.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
2
|
-
|
|
2
|
+
// src/storage/domains/memory-settings/base.ts
|
|
3
3
|
/**
|
|
4
4
|
* Sentinel `user_id` for a factory project's shared memory settings. Factory
|
|
5
5
|
* runs are org-shared, so their OM configuration lives on the project — this
|
|
@@ -123,7 +123,6 @@ var MemorySettingsStorage = class extends FactoryStorageDomain {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
};
|
|
126
|
-
//#endregion
|
|
127
126
|
export { MEMORY_SETTINGS_SCHEMA, MemorySettingsStorage, factoryMemorySettingsUserId };
|
|
128
127
|
|
|
129
128
|
//# sourceMappingURL=base.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
2
2
|
import { isThinkingLevelSetting } from "@mastra/code-sdk/thinking";
|
|
3
|
-
|
|
3
|
+
// src/storage/domains/model-defaults/base.ts
|
|
4
4
|
const USER_DEFAULT_MODELS_SCHEMA = {
|
|
5
5
|
name: "user_default_models",
|
|
6
6
|
columns: {
|
|
@@ -91,7 +91,6 @@ var ModelDefaultsStorage = class extends FactoryStorageDomain {
|
|
|
91
91
|
}) > 0;
|
|
92
92
|
}
|
|
93
93
|
};
|
|
94
|
-
//#endregion
|
|
95
94
|
export { ModelDefaultsStorage, USER_DEFAULT_MODELS_SCHEMA };
|
|
96
95
|
|
|
97
96
|
//# sourceMappingURL=base.js.map
|
|
@@ -2,7 +2,6 @@ import type { ThinkingLevelSetting } from '@mastra/code-sdk/thinking';
|
|
|
2
2
|
import { FactoryStorageDomain } from '@mastra/core/storage';
|
|
3
3
|
import type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';
|
|
4
4
|
export declare const DEFAULT_BUILD_PUSH_DEBOUNCE_MINUTES = 10;
|
|
5
|
-
export declare const DEFAULT_FACTORY_THINKING_LEVEL: ThinkingLevelSetting;
|
|
6
5
|
export declare const FACTORY_MODEL_SCOPES: readonly ["factory", "user", "hybrid"];
|
|
7
6
|
export type FactoryModelScope = (typeof FACTORY_MODEL_SCOPES)[number];
|
|
8
7
|
/** The single credential scope one session or run resolves from; `hybrid` is never effective. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/projects/base.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/projects/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { DEFAULT_THINKING_LEVEL } from "../../../default-thinking-level.js";
|
|
1
2
|
import { FactoryStorageDomain } from "@mastra/core/storage";
|
|
2
3
|
import { isThinkingLevelSetting } from "@mastra/code-sdk/thinking";
|
|
3
|
-
|
|
4
|
+
// src/storage/domains/projects/base.ts
|
|
4
5
|
const DEFAULT_BUILD_PUSH_DEBOUNCE_MINUTES = 10;
|
|
5
|
-
const DEFAULT_FACTORY_THINKING_LEVEL = "medium";
|
|
6
6
|
const FACTORY_MODEL_SCOPES = [
|
|
7
7
|
"factory",
|
|
8
8
|
"user",
|
|
@@ -37,7 +37,7 @@ const FACTORY_PROJECTS_SCHEMA = {
|
|
|
37
37
|
},
|
|
38
38
|
default_thinking_level: {
|
|
39
39
|
type: "text",
|
|
40
|
-
default:
|
|
40
|
+
default: DEFAULT_THINKING_LEVEL
|
|
41
41
|
},
|
|
42
42
|
slack_work_items_enabled: {
|
|
43
43
|
type: "boolean",
|
|
@@ -141,7 +141,7 @@ function toFactoryProject(row) {
|
|
|
141
141
|
description: row.description,
|
|
142
142
|
defaultModelId: row.default_model_id,
|
|
143
143
|
modelScope: row.model_scope === "factory" || row.model_scope === "user" ? row.model_scope : "hybrid",
|
|
144
|
-
defaultThinkingLevel: isThinkingLevelSetting(row.default_thinking_level) ? row.default_thinking_level :
|
|
144
|
+
defaultThinkingLevel: isThinkingLevelSetting(row.default_thinking_level) ? row.default_thinking_level : DEFAULT_THINKING_LEVEL,
|
|
145
145
|
autoRunEnabled: row.auto_run_enabled,
|
|
146
146
|
autoApprovePlans: row.auto_approve_plans ?? false,
|
|
147
147
|
sandboxWorkingDirectory: row.sandbox_working_directory ?? null,
|
|
@@ -366,7 +366,6 @@ var FactoryProjectsStorage = class extends FactoryStorageDomain {
|
|
|
366
366
|
}) > 0 ? project : null;
|
|
367
367
|
}
|
|
368
368
|
};
|
|
369
|
-
|
|
370
|
-
export { DEFAULT_BUILD_PUSH_DEBOUNCE_MINUTES, DEFAULT_FACTORY_THINKING_LEVEL, FACTORY_MODEL_SCOPES, FACTORY_PROJECTS_SCHEMA, FactoryProjectsStorage, effectiveModelScope };
|
|
369
|
+
export { DEFAULT_BUILD_PUSH_DEBOUNCE_MINUTES, FACTORY_MODEL_SCOPES, FACTORY_PROJECTS_SCHEMA, FactoryProjectsStorage, effectiveModelScope };
|
|
371
370
|
|
|
372
371
|
//# sourceMappingURL=base.js.map
|