import { n as __decorateMetadata, t as __decorateParam } from "./decorateParam-BWxkAUSj.js";
import { t as __decorate } from "./decorate-CXWmflG_.js";
import { AgentConfigInspector, AgentConnectionNodeCollector, ConnectionNodeIdFactory, CoreTokens, CredentialUnboundError, inject, injectable } from "@codemation/core";
import { createCipheriv, createDecipheriv, createHash, hkdfSync, randomBytes, randomUUID } from "node:crypto";

//#region src/infrastructure/credentials/OpenAiApiKeyCredentialHealthTester.ts
/**
* Verifies an OpenAI-compatible API key by calling the provider's models list endpoint
* (GET `/v1/models` relative to the configured base URL).
*/
var OpenAiApiKeyCredentialHealthTester = class {
	constructor(fetchImpl) {
		this.fetchImpl = fetchImpl;
	}
	async test(args) {
		const testedAt = (/* @__PURE__ */ new Date()).toISOString();
		const apiKey = String(args.material.apiKey ?? "").trim();
		if (apiKey.length === 0) return {
			status: "failing",
			message: "OpenAI API key is empty.",
			testedAt
		};
		const modelsUrl = this.resolveModelsListUrl(args.publicConfig.baseUrl);
		try {
			const response = await this.fetchImpl(modelsUrl, {
				method: "GET",
				headers: { Authorization: `Bearer ${apiKey}` },
				signal: AbortSignal.timeout(25e3)
			});
			if (response.ok) return {
				status: "healthy",
				message: "API key verified against the models endpoint.",
				testedAt
			};
			return {
				status: "failing",
				message: await this.parseErrorMessage(response),
				testedAt
			};
		} catch (error) {
			return {
				status: "failing",
				message: error instanceof Error ? error.message : String(error),
				testedAt
			};
		}
	}
	resolveModelsListUrl(baseUrlRaw) {
		const defaultBase = "https://api.openai.com/v1";
		const raw = typeof baseUrlRaw === "string" ? baseUrlRaw.trim() : "";
		const base = raw === "" ? defaultBase : raw.replace(/\/+$/, "");
		if (base.endsWith("/models")) return base;
		if (base.endsWith("/v1")) return `${base}/models`;
		return `${base}/v1/models`;
	}
	async parseErrorMessage(response) {
		const prefix = `HTTP ${response.status}`;
		try {
			const text = await response.text();
			if (text.trim() === "") return prefix;
			const fromApi = JSON.parse(text).error?.message;
			if (typeof fromApi === "string" && fromApi.trim() !== "") return `${prefix}: ${fromApi.trim()}`;
			return `${prefix}: ${text.length > 280 ? `${text.slice(0, 280)}…` : text}`;
		} catch {
			return prefix;
		}
	}
};

//#endregion
//#region src/infrastructure/credentials/OpenAiApiKeyCredentialTypeFactory.ts
/**
* Builds the OpenAI-compatible API key credential (`openai.apiKey`) registration.
* Used by {@link FrameworkBuiltinCredentialTypesRegistrar} and may be listed in {@link CodemationConfig.credentialTypes}
* so consumer apps always register the type even when bootstrap order differs.
*/
var OpenAiApiKeyCredentialTypeFactory = class {
	constructor(healthTester) {
		this.healthTester = healthTester;
	}
	createCredentialType() {
		return {
			definition: {
				typeId: "openai.apiKey",
				displayName: "OpenAI API key",
				description: "API key and optional base URL for OpenAI or OpenAI-compatible chat endpoints.",
				publicFields: [{
					key: "baseUrl",
					label: "Base URL",
					type: "string",
					placeholder: "https://api.openai.com/v1",
					helpText: "Leave empty to use the default OpenAI API endpoint."
				}],
				secretFields: [{
					key: "apiKey",
					label: "API key",
					type: "password",
					required: true
				}],
				supportedSourceKinds: [
					"db",
					"env",
					"code"
				]
			},
			createSession: async (args) => {
				const baseUrlRaw = args.publicConfig.baseUrl;
				const baseUrl = typeof baseUrlRaw === "string" && baseUrlRaw.trim() !== "" ? baseUrlRaw.trim() : void 0;
				return {
					apiKey: String(args.material.apiKey ?? ""),
					baseUrl
				};
			},
			test: async (args) => this.healthTester.test(args)
		};
	}
};

//#endregion
//#region src/applicationTokens.ts
const ApplicationTokens = {
	CodemationAuthConfig: Symbol.for("codemation.application.CodemationAuthConfig"),
	CodemationWhitelabelConfig: Symbol.for("codemation.application.CodemationWhitelabelConfig"),
	AppConfig: Symbol.for("codemation.application.AppConfig"),
	WebSocketPort: Symbol.for("codemation.application.WebSocketPort"),
	WebSocketBindHost: Symbol.for("codemation.application.WebSocketBindHost"),
	QueryBus: Symbol.for("codemation.application.QueryBus"),
	CommandBus: Symbol.for("codemation.application.CommandBus"),
	DomainEventBus: Symbol.for("codemation.application.DomainEventBus"),
	QueryHandler: Symbol.for("codemation.application.QueryHandler"),
	CommandHandler: Symbol.for("codemation.application.CommandHandler"),
	DomainEventHandler: Symbol.for("codemation.application.DomainEventHandler"),
	HonoApiRouteRegistrar: Symbol.for("codemation.application.HonoApiRouteRegistrar"),
	InternalHonoApiRouteRegistrar: Symbol.for("codemation.application.InternalHonoApiRouteRegistrar"),
	ManagedCorsMiddleware: Symbol.for("codemation.application.ManagedCorsMiddleware"),
	WebsocketAuthenticator: Symbol.for("codemation.application.WebsocketAuthenticator"),
	WorkflowWebsocketPublisher: Symbol.for("codemation.application.WorkflowWebsocketPublisher"),
	TelemetrySpanPublisher: Symbol.for("codemation.application.TelemetrySpanPublisher"),
	WorkerRuntimeScheduler: Symbol.for("codemation.application.WorkerRuntimeScheduler"),
	WorkflowDefinitionRepository: Symbol.for("codemation.application.WorkflowDefinitionRepository"),
	WorkflowActivationRepository: Symbol.for("codemation.application.WorkflowActivationRepository"),
	WorkflowDebuggerOverlayRepository: Symbol.for("codemation.application.WorkflowDebuggerOverlayRepository"),
	WorkflowRunRepository: Symbol.for("codemation.application.WorkflowRunRepository"),
	LoggerFactory: Symbol.for("codemation.application.LoggerFactory"),
	PerformanceDiagnosticsLogger: Symbol.for("codemation.application.PerformanceDiagnosticsLogger"),
	CredentialStore: Symbol.for("codemation.application.CredentialStore"),
	RunTraceContextRepository: Symbol.for("codemation.application.RunTraceContextRepository"),
	TelemetrySpanStore: Symbol.for("codemation.application.TelemetrySpanStore"),
	TelemetryArtifactStore: Symbol.for("codemation.application.TelemetryArtifactStore"),
	TelemetryMetricPointStore: Symbol.for("codemation.application.TelemetryMetricPointStore"),
	TelemetryExporter: Symbol.for("codemation.application.TelemetryExporter"),
	PrismaClient: Symbol.for("codemation.application.PrismaClient"),
	SessionVerifier: Symbol.for("codemation.application.SessionVerifier"),
	Clock: Symbol.for("codemation.application.Clock"),
	WorkflowAuditEmitter: Symbol.for("codemation.application.WorkflowAuditEmitter"),
	ProcessRunner: Symbol.for("codemation.application.ProcessRunner"),
	OAuthFlowExecutor: Symbol.for("codemation.application.OAuthFlowExecutor"),
	CredentialMaterialInnerProvider: Symbol.for("codemation.application.CredentialMaterialInnerProvider")
};

//#endregion
//#region src/domain/credentials/CredentialTypeRegistryImpl.ts
const SOURCE_PRIORITY$1 = {
	plugin: 0,
	config: 1,
	controlPlane: 2
};
let CredentialTypeRegistryImpl = class CredentialTypeRegistryImpl$1 {
	entries = /* @__PURE__ */ new Map();
	bySource = /* @__PURE__ */ new Map();
	constructor(loggers) {
		this.loggers = loggers;
	}
	merge(source, types) {
		const logger = this.loggers.create("CredentialTypeRegistryImpl");
		for (const type of types) this.insert(source, type, logger);
	}
	mergeDefinitions(source, definitions) {
		const logger = this.loggers.create("CredentialTypeRegistryImpl");
		for (const definition of definitions) {
			const existing = this.entries.get(definition.typeId);
			const sourcePriority = SOURCE_PRIORITY$1[source];
			if (existing) {
				if (sourcePriority < SOURCE_PRIORITY$1[existing.source]) {
					logger.warn(`CredentialTypeRegistryImpl: id collision — lower-priority source "${source}" ignored for typeId "${definition.typeId}" (current source: "${existing.source}")`);
					continue;
				}
				if (sourcePriority > SOURCE_PRIORITY$1[existing.source]) {
					logger.warn(`CredentialTypeRegistryImpl: typeId "${definition.typeId}" shadowed — "${existing.source}" overridden by higher-priority source "${source}"`);
					this.bySource.get(existing.source)?.delete(definition.typeId);
				}
				const nextType = sourcePriority === SOURCE_PRIORITY$1[existing.source] ? {
					...existing.type,
					definition
				} : {
					definition,
					createSession: this.createUnsupportedSessionFactory(definition.typeId, source),
					test: this.createUnsupportedHealthTester(definition.typeId, source)
				};
				this.recordEntry(definition.typeId, {
					type: nextType,
					source
				});
				continue;
			}
			const stubType = {
				definition,
				createSession: this.createUnsupportedSessionFactory(definition.typeId, source),
				test: this.createUnsupportedHealthTester(definition.typeId, source)
			};
			this.recordEntry(definition.typeId, {
				type: stubType,
				source
			});
		}
	}
	clear(source) {
		const ids = this.bySource.get(source);
		if (!ids) return;
		for (const id of ids) this.entries.delete(id);
		this.bySource.delete(source);
	}
	listTypes() {
		return [...this.entries.values()].map((entry) => entry.type.definition);
	}
	getType(typeId) {
		return this.entries.get(typeId)?.type.definition;
	}
	getCredentialType(typeId) {
		return this.entries.get(typeId)?.type;
	}
	insert(source, type, logger) {
		const typeId = type.definition.typeId;
		const existing = this.entries.get(typeId);
		const sourcePriority = SOURCE_PRIORITY$1[source];
		if (existing) {
			if (sourcePriority < SOURCE_PRIORITY$1[existing.source]) {
				logger.warn(`CredentialTypeRegistryImpl: id collision — lower-priority source "${source}" ignored for typeId "${typeId}" (current source: "${existing.source}")`);
				return;
			}
			if (sourcePriority > SOURCE_PRIORITY$1[existing.source]) {
				logger.warn(`CredentialTypeRegistryImpl: typeId "${typeId}" shadowed — "${existing.source}" overridden by higher-priority source "${source}"`);
				this.bySource.get(existing.source)?.delete(typeId);
			}
		}
		this.recordEntry(typeId, {
			type,
			source
		});
	}
	recordEntry(typeId, entry) {
		this.entries.set(typeId, entry);
		if (!this.bySource.has(entry.source)) this.bySource.set(entry.source, /* @__PURE__ */ new Set());
		this.bySource.get(entry.source).add(typeId);
	}
	createUnsupportedSessionFactory(typeId, source) {
		return async () => {
			throw new Error(`Credential type "${typeId}" (source "${source}") was registered with definition only — no createSession implementation is available in this runtime.`);
		};
	}
	createUnsupportedHealthTester(typeId, source) {
		return async () => ({
			status: "unknown",
			message: `Credential type "${typeId}" (source "${source}") has no local test implementation.`
		});
	}
};
CredentialTypeRegistryImpl = __decorate([
	injectable(),
	__decorateParam(0, inject(ApplicationTokens.LoggerFactory)),
	__decorateMetadata("design:paramtypes", [Object])
], CredentialTypeRegistryImpl);

//#endregion
//#region src/application/ApplicationRequestError.ts
var ApplicationRequestError = class extends Error {
	status;
	payload;
	constructor(status, message, errors) {
		super(message);
		this.name = "ApplicationRequestError";
		this.status = status;
		this.payload = errors && errors.length > 0 ? {
			error: message,
			errors
		} : { error: message };
	}
};

//#endregion
//#region src/mcp/McpServerCatalog.ts
const SOURCE_PRIORITY = {
	plugin: 0,
	config: 1,
	controlPlane: 2
};
const ID_PATTERN = /^[a-z0-9-]+$/;
let McpServerCatalog = class McpServerCatalog$1 {
	entries = /* @__PURE__ */ new Map();
	bySource = /* @__PURE__ */ new Map();
	env;
	constructor(loggers, appConfig) {
		this.loggers = loggers;
		this.env = appConfig.env;
	}
	merge(source, declarations) {
		const logger = this.loggers.create("McpServerCatalog");
		for (const decl of declarations) {
			if (!this.validate(decl, source, logger)) continue;
			const existing = this.entries.get(decl.id);
			if (existing) {
				if (SOURCE_PRIORITY[source] <= SOURCE_PRIORITY[existing.source]) {
					logger.warn(`McpServerCatalog: id collision — lower-priority source "${source}" ignored for id "${decl.id}" (current source: "${existing.source}")`);
					continue;
				}
				logger.warn(`McpServerCatalog: id "${decl.id}" shadowed — "${existing.source}" overridden by higher-priority source "${source}"`);
				this.bySource.get(existing.source)?.delete(decl.id);
			}
			this.entries.set(decl.id, {
				decl,
				source
			});
			if (!this.bySource.has(source)) this.bySource.set(source, /* @__PURE__ */ new Set());
			this.bySource.get(source).add(decl.id);
		}
	}
	get(id) {
		return this.entries.get(id)?.decl;
	}
	getAll() {
		return [...this.entries.values()].map((entry) => entry.decl);
	}
	clear(source) {
		const ids = this.bySource.get(source);
		if (!ids) return;
		for (const id of ids) this.entries.delete(id);
		this.bySource.delete(source);
	}
	validate(decl, source, logger) {
		if (!ID_PATTERN.test(decl.id)) {
			logger.warn(`McpServerCatalog: declaration from "${source}" has invalid id "${decl.id}" (must match /^[a-z0-9-]+$/) — skipped`);
			return false;
		}
		if (decl.transport === "stdio") {
			if (this.env.CODEMATION_ALLOW_STDIO_MCP !== "true") {
				logger.warn(`McpServerCatalog: declaration "${decl.id}" from "${source}" uses stdio transport which is disabled (set CODEMATION_ALLOW_STDIO_MCP=true to allow) — skipped`);
				return false;
			}
		}
		return true;
	}
};
McpServerCatalog = __decorate([
	injectable(),
	__decorateParam(0, inject(ApplicationTokens.LoggerFactory)),
	__decorateParam(1, inject(ApplicationTokens.AppConfig)),
	__decorateMetadata("design:paramtypes", [Object, Object])
], McpServerCatalog);

//#endregion
//#region src/domain/credentials/WorkflowCredentialNodeResolver.ts
var _ref$6;
let WorkflowCredentialNodeResolver = class WorkflowCredentialNodeResolver$1 {
	constructor(mcpCatalog) {
		this.mcpCatalog = mcpCatalog;
	}
	/**
	* Human-readable label for credential errors (workflow node name or agent › attachment).
	*/
	describeCredentialNodeDisplay(workflow, nodeId) {
		const direct = workflow.nodes.find((n) => n.id === nodeId);
		if (direct) return direct.name ?? direct.config.name ?? direct.id;
		const recursive = this.findRecursiveConnectionNode(workflow, nodeId);
		if (!recursive) return nodeId;
		return this.buildRecursiveDisplayLabel(recursive.rootAgentLabel, recursive.entry, recursive.entriesById);
	}
	isCredentialNodeIdInWorkflow(workflow, nodeId) {
		if (workflow.nodes.some((n) => n.id === nodeId)) return true;
		return this.findRecursiveConnectionNode(workflow, nodeId) !== void 0;
	}
	findRequirement(workflow, nodeId, slotKey) {
		const direct = this.findDirectRequirement(workflow, nodeId, slotKey);
		if (direct) return direct;
		const recursive = this.findRecursiveConnectionNode(workflow, nodeId);
		if (!recursive) return;
		const requirement = recursive.entry.credentialSource.getCredentialRequirements?.()?.find((entry) => entry.slotKey === slotKey);
		return requirement ? {
			nodeName: recursive.entry.name,
			requirement
		} : void 0;
	}
	listSlots(workflow) {
		const slotsByKey = /* @__PURE__ */ new Map();
		for (const node of workflow.nodes) {
			if (AgentConfigInspector.isAgentNodeConfig(node.config)) {
				this.addRecursiveAgentSlots(workflow.id, node.id, node.config, slotsByKey);
				continue;
			}
			this.addSlotsForRequirements(workflow.id, node.id, node.name ?? node.config.name ?? node.id, node.config.getCredentialRequirements?.() ?? [], slotsByKey);
		}
		return [...slotsByKey.values()];
	}
	findDirectRequirement(workflow, nodeId, slotKey) {
		const node = workflow.nodes.find((entry) => entry.id === nodeId);
		if (!node || AgentConfigInspector.isAgentNodeConfig(node.config)) return;
		const requirement = node.config.getCredentialRequirements?.()?.find((entry) => entry.slotKey === slotKey);
		if (!requirement) return;
		return {
			nodeName: node.name ?? node.config.name ?? node.id,
			requirement
		};
	}
	addRecursiveAgentSlots(workflowId, rootAgentNodeId, agentConfig, slotsByKey) {
		const mcpResolver = this.mcpCatalog ? (id) => this.mcpCatalog.get(id) : void 0;
		const descriptors = AgentConnectionNodeCollector.collect(rootAgentNodeId, agentConfig, mcpResolver);
		for (const entry of descriptors) this.addSlotsForRequirements(workflowId, entry.nodeId, entry.name, entry.credentialSource.getCredentialRequirements?.() ?? [], slotsByKey);
	}
	addSlotsForRequirements(workflowId, nodeId, nodeName, requirements, slotsByKey) {
		for (const requirement of requirements) {
			const key = `${nodeId}\0${requirement.slotKey}`;
			if (slotsByKey.has(key)) continue;
			slotsByKey.set(key, {
				workflowId,
				nodeId,
				nodeName,
				requirement
			});
		}
	}
	findRecursiveConnectionNode(workflow, nodeId) {
		if (!ConnectionNodeIdFactory.isLanguageModelConnectionNodeId(nodeId) && !ConnectionNodeIdFactory.isToolConnectionNodeId(nodeId) && !ConnectionNodeIdFactory.isMcpConnectionNodeId(nodeId)) return;
		const mcpResolver = this.mcpCatalog ? (id) => this.mcpCatalog.get(id) : void 0;
		for (const node of workflow.nodes) {
			if (!AgentConfigInspector.isAgentNodeConfig(node.config)) continue;
			const entries = AgentConnectionNodeCollector.collect(node.id, node.config, mcpResolver);
			const entriesById = new Map(entries.map((entry$1) => [entry$1.nodeId, entry$1]));
			const entry = entriesById.get(nodeId);
			if (!entry) continue;
			return {
				rootAgentNodeId: node.id,
				rootAgentLabel: node.name ?? node.config.name ?? node.id,
				entry,
				entriesById
			};
		}
	}
	buildRecursiveDisplayLabel(rootAgentLabel, entry, entriesById) {
		const labels = [rootAgentLabel, ...this.collectAncestorToolLabels(entry.parentNodeId, entriesById)];
		labels.push(entry.role === "languageModel" ? "Language model" : entry.name);
		return labels.join(" › ");
	}
	collectAncestorToolLabels(parentNodeId, entriesById) {
		const labels = [];
		let currentNodeId = parentNodeId;
		while (true) {
			const parentEntry = entriesById.get(currentNodeId);
			if (!parentEntry) return labels.reverse();
			if (parentEntry.role === "tool" || parentEntry.role === "nestedAgent") labels.push(parentEntry.name);
			currentNodeId = parentEntry.parentNodeId;
		}
	}
};
WorkflowCredentialNodeResolver = __decorate([
	injectable(),
	__decorateParam(0, inject(McpServerCatalog)),
	__decorateMetadata("design:paramtypes", [typeof (_ref$6 = typeof McpServerCatalog !== "undefined" && McpServerCatalog) === "function" ? _ref$6 : Object])
], WorkflowCredentialNodeResolver);

//#endregion
//#region src/domain/credentials/CredentialFieldEnvOverlayService.ts
let CredentialFieldEnvOverlayService = class CredentialFieldEnvOverlayService$1 {
	constructor(appConfig) {
		this.appConfig = appConfig;
	}
	/** True when the field declares an env var and process.env has a non-empty string for it. */
	isFieldResolvedFromEnv(field) {
		const name = field.envVarName?.trim();
		if (!name) return false;
		const v = this.appConfig.env[name];
		return typeof v === "string" && v.length > 0;
	}
	apply(args) {
		const pub = { ...args.publicConfig };
		const mat = { ...args.material };
		for (const field of args.definition.publicFields ?? []) {
			const name = field.envVarName?.trim();
			if (!name) continue;
			const v = this.appConfig.env[name];
			if (typeof v === "string" && v.length > 0) pub[field.key] = v;
		}
		for (const field of args.definition.secretFields ?? []) {
			const name = field.envVarName?.trim();
			if (!name) continue;
			const v = this.appConfig.env[name];
			if (typeof v === "string" && v.length > 0) mat[field.key] = v;
		}
		return Object.freeze({
			resolvedPublicConfig: Object.freeze(pub),
			resolvedMaterial: Object.freeze(mat)
		});
	}
};
CredentialFieldEnvOverlayService = __decorate([
	injectable(),
	__decorateParam(0, inject(ApplicationTokens.AppConfig)),
	__decorateMetadata("design:paramtypes", [Object])
], CredentialFieldEnvOverlayService);

//#endregion
//#region src/domain/credentials/CredentialKeyRotatedError.ts
/**
* Thrown by {@link CredentialSecretCipher.decrypt} when the credential's stored
* `encryptionKeyId` does not match the current master key's id.
*
* This indicates the `CODEMATION_CREDENTIALS_MASTER_KEY` environment variable has
* been rotated since the credential was encrypted. The operator must re-bind the
* affected credential (which re-encrypts it with the new key).
*
* See {@link docs/security-boundary.md} for the key rotation contract.
*/
var CredentialKeyRotatedError = class extends Error {
	storedKeyId;
	constructor(storedKeyId) {
		super(`Credential was encrypted with key "${storedKeyId}" but the current master key produces a different id. Re-bind the credential to re-encrypt it with the active key.`);
		this.name = "CredentialKeyRotatedError";
		this.storedKeyId = storedKeyId;
	}
};

//#endregion
//#region src/domain/credentials/CredentialSecretCipher.ts
var _CredentialSecretCipher;
let CredentialSecretCipher = class CredentialSecretCipher$1 {
	static {
		_CredentialSecretCipher = this;
	}
	static algorithm = "aes-256-gcm";
	static currentSchemaVersion = 2;
	static ivLength = 12;
	static HKDF_SALT = "codemation/credential-cipher/v1";
	static HKDF_INFO = "aes-256-gcm-key";
	constructor(appConfig) {
		this.appConfig = appConfig;
	}
	encrypt(value) {
		const iv = randomBytes(_CredentialSecretCipher.ivLength);
		const cipher = createCipheriv(_CredentialSecretCipher.algorithm, this.resolveKeyMaterialV2(), iv);
		const plaintext = Buffer.from(JSON.stringify(value), "utf8");
		const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
		const authTag = cipher.getAuthTag();
		return {
			encryptedJson: Buffer.concat([
				iv,
				authTag,
				encrypted
			]).toString("base64"),
			encryptionKeyId: this.resolveKeyId(),
			schemaVersion: _CredentialSecretCipher.currentSchemaVersion
		};
	}
	decrypt(record) {
		const keyMaterial = (record.schemaVersion ?? 1) >= 2 ? this.resolveKeyMaterialV2() : this.resolveKeyMaterialV1();
		const currentKeyId = this.resolveKeyId();
		if (record.encryptionKeyId !== currentKeyId) throw new CredentialKeyRotatedError(record.encryptionKeyId);
		const packed = Buffer.from(record.encryptedJson, "base64");
		const iv = packed.subarray(0, _CredentialSecretCipher.ivLength);
		const authTag = packed.subarray(_CredentialSecretCipher.ivLength, _CredentialSecretCipher.ivLength + 16);
		const encrypted = packed.subarray(_CredentialSecretCipher.ivLength + 16);
		const decipher = createDecipheriv(_CredentialSecretCipher.algorithm, keyMaterial, iv);
		decipher.setAuthTag(authTag);
		const plaintext = Buffer.concat([decipher.update(encrypted), decipher.final()]).toString("utf8");
		return JSON.parse(plaintext);
	}
	/**
	* Current (v2) key derivation: HKDF-SHA-256 with a fixed application salt and info label.
	* Input must be a base64-encoded 32-byte value (`CODEMATION_CREDENTIALS_MASTER_KEY`).
	*/
	resolveKeyMaterialV2() {
		const ikm = this.resolveBase64Key32Bytes();
		return Buffer.from(hkdfSync("sha256", ikm, Buffer.from(_CredentialSecretCipher.HKDF_SALT, "utf8"), Buffer.from(_CredentialSecretCipher.HKDF_INFO, "utf8"), 32));
	}
	/**
	* Legacy (v1) key derivation: SHA-256 of the raw env string.
	* Retained for decrypt-side backward compatibility only.
	*/
	resolveKeyMaterialV1() {
		const rawValue = this.appConfig.env.CODEMATION_CREDENTIALS_MASTER_KEY;
		if (!rawValue || rawValue.trim().length === 0) throw new Error("CODEMATION_CREDENTIALS_MASTER_KEY is required to encrypt database-managed credentials.");
		return createHash("sha256").update(rawValue).digest();
	}
	/**
	* Validates and returns the raw 32-byte key material from the env var.
	* Throws if the env var is absent or does not decode to exactly 32 bytes.
	*/
	resolveBase64Key32Bytes() {
		const rawValue = this.appConfig.env.CODEMATION_CREDENTIALS_MASTER_KEY;
		if (!rawValue || rawValue.trim().length === 0) throw new Error("CODEMATION_CREDENTIALS_MASTER_KEY is required to encrypt database-managed credentials.");
		const decoded = Buffer.from(rawValue.trim(), "base64");
		if (decoded.length !== 32) throw new Error(`CODEMATION_CREDENTIALS_MASTER_KEY must be a base64-encoded 32-byte value (got ${decoded.length} bytes). Generate a valid key with: openssl rand -base64 32`);
		return decoded;
	}
	resolveKeyId() {
		const rawValue = this.appConfig.env.CODEMATION_CREDENTIALS_MASTER_KEY;
		return createHash("sha256").update(rawValue ?? "").digest("hex").slice(0, 12);
	}
};
CredentialSecretCipher = _CredentialSecretCipher = __decorate([
	injectable(),
	__decorateParam(0, inject(ApplicationTokens.AppConfig)),
	__decorateMetadata("design:paramtypes", [Object])
], CredentialSecretCipher);

//#endregion
//#region src/domain/credentials/CredentialMaterialResolver.ts
var _ref$5;
let CredentialMaterialResolver = class CredentialMaterialResolver$1 {
	constructor(credentialStore, credentialSecretCipher, appConfig) {
		this.credentialStore = credentialStore;
		this.credentialSecretCipher = credentialSecretCipher;
		this.appConfig = appConfig;
	}
	async resolveMaterial(instance) {
		if (instance.secretRef.kind === "db") {
			const secretMaterial = await this.credentialStore.getSecretMaterial(instance.instanceId);
			if (!secretMaterial) throw new Error(`Credential ${instance.instanceId} is missing encrypted secret material.`);
			return this.credentialSecretCipher.decrypt(secretMaterial);
		}
		if (instance.secretRef.kind === "env") return this.resolveEnvMaterial(instance);
		return instance.secretRef.value;
	}
	resolveEnvMaterial(instance) {
		if (instance.secretRef.kind !== "env") throw new Error(`Credential ${instance.instanceId} is not environment-backed.`);
		const resolved = {};
		const missingEnvironmentVariables = [];
		for (const [fieldKey, envVarName] of Object.entries(instance.secretRef.envByField)) {
			const value = this.appConfig.env[envVarName];
			if (value === void 0 || value.length === 0) {
				missingEnvironmentVariables.push(envVarName);
				continue;
			}
			resolved[fieldKey] = value;
		}
		if (missingEnvironmentVariables.length > 0) throw new Error(`Credential ${instance.instanceId} requires environment variables that are not set: ${missingEnvironmentVariables.join(", ")}.`);
		return resolved;
	}
};
CredentialMaterialResolver = __decorate([
	injectable(),
	__decorateParam(0, inject(ApplicationTokens.CredentialStore)),
	__decorateParam(1, inject(CredentialSecretCipher)),
	__decorateParam(2, inject(ApplicationTokens.AppConfig)),
	__decorateMetadata("design:paramtypes", [
		Object,
		typeof (_ref$5 = typeof CredentialSecretCipher !== "undefined" && CredentialSecretCipher) === "function" ? _ref$5 : Object,
		Object
	])
], CredentialMaterialResolver);

//#endregion
//#region src/domain/credentials/CredentialOAuth2ScopeResolver.ts
let CredentialOAuth2ScopeResolver = class CredentialOAuth2ScopeResolver$1 {
	resolveRequestedScopes(auth, publicConfig) {
		const scopesFromPublicConfig = auth.scopesFromPublicConfig;
		if (!scopesFromPublicConfig) return [...auth.scopes];
		const preset = this.resolveString(publicConfig[scopesFromPublicConfig.presetFieldKey]);
		if (!preset) return [...auth.scopes];
		const presetScopes = scopesFromPublicConfig.presetScopes[preset];
		if (presetScopes) return [...presetScopes];
		if (preset !== (scopesFromPublicConfig.customPresetKey ?? "custom")) return [...auth.scopes];
		const customScopes = this.resolveScopeList(publicConfig[scopesFromPublicConfig.customScopesFieldKey ?? "customScopes"]);
		if (customScopes.length > 0) return customScopes;
		return [...auth.scopes];
	}
	resolveString(value) {
		if (typeof value !== "string") return;
		const normalized = value.trim();
		return normalized.length > 0 ? normalized : void 0;
	}
	resolveScopeList(value) {
		if (Array.isArray(value)) return this.dedupe(value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0));
		if (typeof value !== "string") return [];
		return this.dedupe(value.split(/[\s,]+/).map((entry) => entry.trim()).filter((entry) => entry.length > 0));
	}
	dedupe(entries) {
		return [...new Set(entries)];
	}
};
CredentialOAuth2ScopeResolver = __decorate([injectable()], CredentialOAuth2ScopeResolver);

//#endregion
//#region src/domain/credentials/CredentialInstanceService.ts
var _ref$4, _ref2$4, _ref3$3, _ref4$2, _ref5;
let CredentialInstanceService = class CredentialInstanceService$1 {
	constructor(credentialStore, credentialTypeRegistry, credentialSecretCipher, credentialFieldEnvOverlayService, credentialMaterialResolver, credentialOAuth2ScopeResolver, credentialSessionService) {
		this.credentialStore = credentialStore;
		this.credentialTypeRegistry = credentialTypeRegistry;
		this.credentialSecretCipher = credentialSecretCipher;
		this.credentialFieldEnvOverlayService = credentialFieldEnvOverlayService;
		this.credentialMaterialResolver = credentialMaterialResolver;
		this.credentialOAuth2ScopeResolver = credentialOAuth2ScopeResolver;
		this.credentialSessionService = credentialSessionService;
	}
	async listInstances() {
		const instances = await this.credentialStore.listInstances();
		const latestTestResults = await this.credentialStore.getLatestTestResults(instances.map((instance) => instance.instanceId));
		return await Promise.all(instances.map(async (instance) => await this.toDto(instance, latestTestResults.get(instance.instanceId))));
	}
	async getInstance(instanceId) {
		const instance = await this.credentialStore.getInstance(instanceId);
		if (!instance) return;
		const latestTestResult = await this.credentialStore.getLatestTestResult(instanceId);
		return await this.toDto(instance, latestTestResult);
	}
	async getInstanceWithSecrets(instanceId) {
		const instance = await this.credentialStore.getInstance(instanceId);
		if (!instance) return;
		const latestTestResult = await this.credentialStore.getLatestTestResult(instanceId);
		const base = await this.toDto(instance, latestTestResult);
		try {
			const material = await this.credentialMaterialResolver.resolveMaterial(instance);
			const secretConfig = Object.fromEntries(Object.entries(material).map(([k, v]) => [k, String(v ?? "")]));
			const envSecretRefs = instance.secretRef.kind === "env" ? instance.secretRef.envByField : void 0;
			return {
				...base,
				secretConfig,
				envSecretRefs
			};
		} catch {
			return base;
		}
	}
	async create(request) {
		const credentialType = this.requireCredentialType(request.typeId);
		const publicFields = credentialType.definition.publicFields ?? [];
		const secretFields = credentialType.definition.secretFields ?? [];
		this.validateRequestFields({
			displayName: request.displayName,
			publicFields,
			publicConfig: request.publicConfig ?? {},
			secretFields,
			sourceKind: request.sourceKind,
			secretConfig: request.secretConfig ?? {},
			envSecretRefs: request.envSecretRefs ?? {}
		});
		const timestamp = (/* @__PURE__ */ new Date()).toISOString();
		const strippedPublic = this.stripEnvManagedFieldValues(publicFields, request.publicConfig ?? {});
		const strippedSecretForRef = this.stripEnvManagedFieldValues(secretFields, request.secretConfig ?? {});
		const instanceId = randomUUID();
		const instance = {
			instanceId,
			typeId: request.typeId,
			displayName: request.displayName.trim(),
			sourceKind: request.sourceKind,
			publicConfig: Object.freeze({ ...strippedPublic }),
			secretRef: this.createSecretRef(request.sourceKind, strippedSecretForRef, request.envSecretRefs ?? {}),
			tags: Object.freeze([...request.tags ?? []]),
			setupStatus: credentialType.definition.auth?.kind === "oauth2" ? "draft" : "ready",
			createdAt: timestamp,
			updatedAt: timestamp,
			material: {
				source: "local",
				ref: instanceId
			}
		};
		await this.credentialStore.saveInstance({
			instance,
			secretMaterial: this.createSecretMaterial(instance, strippedSecretForRef, timestamp)
		});
		this.credentialSessionService.evictInstance(instance.instanceId);
		return this.toDto(instance, void 0);
	}
	async update(instanceId, request) {
		const existing = await this.requireInstance(instanceId);
		const credentialType = this.requireCredentialType(existing.typeId);
		const mergedPublicRaw = { ...request.publicConfig ?? existing.publicConfig };
		const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
		const nextSecretConfig = request.secretConfig;
		const nextEnvSecretRefs = request.envSecretRefs;
		const secretFields = credentialType.definition.secretFields ?? [];
		this.validateRequestFields({
			displayName: request.displayName ?? existing.displayName,
			publicFields: credentialType.definition.publicFields ?? [],
			publicConfig: mergedPublicRaw,
			secretFields,
			sourceKind: existing.sourceKind,
			secretConfig: nextSecretConfig ?? {},
			envSecretRefs: nextEnvSecretRefs ?? {},
			allowSecretOmission: true
		});
		const publicConfig = Object.freeze({ ...this.stripEnvManagedFieldValues(credentialType.definition.publicFields ?? [], mergedPublicRaw) });
		const mergedSecretForRef = nextSecretConfig !== void 0 ? this.stripEnvManagedFieldValues(secretFields, nextSecretConfig) : void 0;
		const instance = {
			...existing,
			displayName: request.displayName?.trim() || existing.displayName,
			publicConfig,
			tags: Object.freeze([...request.tags ?? existing.tags]),
			setupStatus: request.setupStatus ?? existing.setupStatus,
			secretRef: nextSecretConfig || nextEnvSecretRefs ? this.createSecretRef(existing.sourceKind, mergedSecretForRef ?? {}, nextEnvSecretRefs ?? {}) : existing.secretRef,
			updatedAt
		};
		await this.credentialStore.saveInstance({
			instance,
			secretMaterial: nextSecretConfig !== void 0 && mergedSecretForRef !== void 0 ? this.createSecretMaterial(instance, mergedSecretForRef, updatedAt) : void 0
		});
		this.credentialSessionService.evictInstance(instance.instanceId);
		return this.toDto(instance, await this.credentialStore.getLatestTestResult(instance.instanceId));
	}
	async delete(instanceId) {
		await this.credentialStore.deleteInstance(instanceId);
		this.credentialSessionService.evictInstance(instanceId);
	}
	async disconnectOAuth2(instanceId) {
		const instance = await this.requireInstance(instanceId);
		if (this.requireCredentialType(instance.typeId).definition.auth?.kind !== "oauth2") throw new ApplicationRequestError(400, `Credential instance ${instanceId} does not use OAuth2.`);
		const updatedInstance = {
			...instance,
			setupStatus: "draft",
			updatedAt: (/* @__PURE__ */ new Date()).toISOString()
		};
		await this.credentialStore.saveInstance({ instance: updatedInstance });
		await this.credentialStore.deleteOAuth2Material(instanceId);
		this.credentialSessionService.evictInstance(instanceId);
		return await this.toDto(updatedInstance, await this.credentialStore.getLatestTestResult(instanceId));
	}
	async requireInstance(instanceId) {
		const instance = await this.credentialStore.getInstance(instanceId);
		if (!instance) throw new ApplicationRequestError(404, `Unknown credential instance: ${instanceId}`);
		return instance;
	}
	createSecretRef(sourceKind, secretConfig, envSecretRefs) {
		if (sourceKind === "db") return { kind: "db" };
		if (sourceKind === "env") return {
			kind: "env",
			envByField: Object.freeze({ ...envSecretRefs })
		};
		return {
			kind: "code",
			value: Object.freeze({ ...secretConfig })
		};
	}
	createSecretMaterial(instance, secretConfig, updatedAt) {
		if (instance.sourceKind !== "db") return;
		const encrypted = this.credentialSecretCipher.encrypt(secretConfig);
		return {
			instanceId: instance.instanceId,
			encryptedJson: encrypted.encryptedJson,
			encryptionKeyId: encrypted.encryptionKeyId,
			schemaVersion: encrypted.schemaVersion,
			updatedAt
		};
	}
	validateRequestFields(args) {
		if (!args.displayName || args.displayName.trim().length === 0) throw new ApplicationRequestError(400, "Credential displayName is required.");
		this.assertRequiredFields("publicConfig", args.publicFields, args.publicConfig);
		if (args.sourceKind === "db") {
			if (!args.allowSecretOmission || Object.keys(args.secretConfig).length > 0) this.assertRequiredFields("secretConfig", args.secretFields, args.secretConfig);
			return;
		}
		if (args.sourceKind === "env") {
			if (!args.allowSecretOmission || Object.keys(args.envSecretRefs).length > 0) this.assertRequiredEnvFields(args.secretFields, args.envSecretRefs);
			return;
		}
		if (!args.allowSecretOmission || Object.keys(args.secretConfig).length > 0) this.assertRequiredFields("secretConfig", args.secretFields, args.secretConfig);
	}
	stripEnvManagedFieldValues(fields, value) {
		const out = { ...value };
		for (const field of fields) if (this.credentialFieldEnvOverlayService.isFieldResolvedFromEnv(field)) delete out[field.key];
		return Object.freeze(out);
	}
	assertRequiredFields(fieldName, schema, value) {
		const missing = schema.filter((field) => field.required === true).filter((field) => !this.credentialFieldEnvOverlayService.isFieldResolvedFromEnv(field)).filter((field) => value[field.key] === void 0 || value[field.key] === null || value[field.key] === "").map((field) => field.key);
		if (missing.length > 0) throw new ApplicationRequestError(400, `Missing required ${fieldName} field(s): ${missing.join(", ")}`);
	}
	assertRequiredEnvFields(schema, envSecretRefs) {
		const missing = schema.filter((field) => field.required === true).filter((field) => !this.credentialFieldEnvOverlayService.isFieldResolvedFromEnv(field)).filter((field) => !envSecretRefs[field.key] || envSecretRefs[field.key].trim().length === 0).map((field) => field.key);
		if (missing.length > 0) throw new ApplicationRequestError(400, `Missing required envSecretRefs field(s): ${missing.join(", ")}`);
	}
	requireCredentialType(typeId) {
		const credentialType = this.credentialTypeRegistry.getCredentialType(typeId);
		if (!credentialType) throw new ApplicationRequestError(400, `Unknown credential type: ${typeId}`);
		return credentialType;
	}
	async markOAuth2Connected(instanceId, connectedAt) {
		const instance = await this.requireInstance(instanceId);
		await this.credentialStore.saveInstance({ instance: {
			...instance,
			setupStatus: "ready",
			updatedAt: connectedAt
		} });
		this.credentialSessionService.evictInstance(instanceId);
	}
	async toDto(instance, latestTestResult) {
		const oauth2Connection = await this.toOAuth2ConnectionDto(instance);
		return {
			instanceId: instance.instanceId,
			typeId: instance.typeId,
			displayName: instance.displayName,
			sourceKind: instance.sourceKind,
			publicConfig: instance.publicConfig,
			tags: instance.tags,
			setupStatus: instance.setupStatus,
			createdAt: instance.createdAt,
			updatedAt: instance.updatedAt,
			latestHealth: latestTestResult?.health,
			oauth2Connection
		};
	}
	async toOAuth2ConnectionDto(instance) {
		const credentialType = this.credentialTypeRegistry.getCredentialType(instance.typeId);
		if (credentialType?.definition.auth?.kind !== "oauth2") return;
		const providerId = "providerId" in credentialType.definition.auth ? credentialType.definition.auth.providerId : "custom";
		const material = await this.credentialStore.getOAuth2Material(instance.instanceId);
		if (!material) return {
			status: "disconnected",
			providerId,
			scopes: [...this.credentialOAuth2ScopeResolver.resolveRequestedScopes(credentialType.definition.auth, instance.publicConfig)]
		};
		return {
			status: "connected",
			providerId: material.providerId,
			connectedEmail: material.connectedEmail,
			connectedAt: material.connectedAt,
			scopes: material.scopes,
			updatedAt: material.updatedAt
		};
	}
};
CredentialInstanceService = __decorate([
	injectable(),
	__decorateParam(0, inject(ApplicationTokens.CredentialStore)),
	__decorateParam(1, inject(CredentialTypeRegistryImpl)),
	__decorateParam(2, inject(CredentialSecretCipher)),
	__decorateParam(3, inject(CredentialFieldEnvOverlayService)),
	__decorateParam(4, inject(CredentialMaterialResolver)),
	__decorateParam(5, inject(CredentialOAuth2ScopeResolver)),
	__decorateParam(6, inject(CoreTokens.CredentialSessionService)),
	__decorateMetadata("design:paramtypes", [
		Object,
		typeof (_ref$4 = typeof CredentialTypeRegistryImpl !== "undefined" && CredentialTypeRegistryImpl) === "function" ? _ref$4 : Object,
		typeof (_ref2$4 = typeof CredentialSecretCipher !== "undefined" && CredentialSecretCipher) === "function" ? _ref2$4 : Object,
		typeof (_ref3$3 = typeof CredentialFieldEnvOverlayService !== "undefined" && CredentialFieldEnvOverlayService) === "function" ? _ref3$3 : Object,
		typeof (_ref4$2 = typeof CredentialMaterialResolver !== "undefined" && CredentialMaterialResolver) === "function" ? _ref4$2 : Object,
		typeof (_ref5 = typeof CredentialOAuth2ScopeResolver !== "undefined" && CredentialOAuth2ScopeResolver) === "function" ? _ref5 : Object,
		Object
	])
], CredentialInstanceService);

//#endregion
//#region src/domain/credentials/CredentialBindingService.ts
var _ref$3, _ref2$3;
let CredentialBindingService = class CredentialBindingService$1 {
	logger;
	constructor(credentialStore, credentialInstanceService, workflowRepository, credentialSessionService, workflowCredentialNodeResolver, loggerFactory) {
		this.credentialStore = credentialStore;
		this.credentialInstanceService = credentialInstanceService;
		this.workflowRepository = workflowRepository;
		this.credentialSessionService = credentialSessionService;
		this.workflowCredentialNodeResolver = workflowCredentialNodeResolver;
		this.logger = loggerFactory.create("CredentialBindingService");
	}
	async upsertBinding(args) {
		const workflow = this.requireWorkflow(args.workflowId);
		const requirement = this.requireRequirement(workflow, args.nodeId, args.slotKey);
		const instance = await this.credentialInstanceService.requireInstance(args.instanceId);
		if (!requirement.acceptedTypes.includes(instance.typeId)) throw new ApplicationRequestError(400, `Credential instance ${instance.instanceId} (${instance.typeId}) is not compatible with slot ${args.slotKey}. Accepted types: ${requirement.acceptedTypes.join(", ")}`);
		const binding = {
			key: {
				workflowId: args.workflowId,
				nodeId: args.nodeId,
				slotKey: args.slotKey
			},
			instanceId: args.instanceId,
			updatedAt: (/* @__PURE__ */ new Date()).toISOString()
		};
		await this.credentialStore.upsertBinding(binding);
		this.credentialSessionService.evictBinding(binding.key);
		return binding;
	}
	async assertRequiredCredentialsBound(workflowId) {
		const workflow = this.requireWorkflow(workflowId);
		const bindings = await this.credentialStore.listBindingsByWorkflowId(workflowId);
		const boundKeys = new Set(bindings.map((b) => this.toBindingKeyString(b.key)));
		const unboundByDb = this.workflowCredentialNodeResolver.listSlots(workflow).filter((slot) => !slot.requirement.optional).filter((slot) => !boundKeys.has(this.toBindingKeyString({
			workflowId,
			nodeId: slot.nodeId,
			slotKey: slot.requirement.slotKey
		})));
		if (unboundByDb.length === 0) return;
		const confirmed = [];
		for (const slot of unboundByDb) try {
			await this.credentialSessionService.getSession({
				workflowId,
				nodeId: slot.nodeId,
				slotKey: slot.requirement.slotKey
			});
		} catch (error) {
			if (!(error instanceof CredentialUnboundError)) this.logger.debug(`CredentialBindingService: unexpected error resolving session for slot ${slot.requirement.slotKey} on ${slot.nodeId}`, error instanceof Error ? error : void 0);
			confirmed.push(slot);
		}
		if (confirmed.length === 0) return;
		const descriptions = confirmed.map((slot) => `"${slot.requirement.label}" on ${slot.nodeName ?? slot.nodeId}`).join(", ");
		throw new ApplicationRequestError(400, `Cannot run workflow: required credential slot${confirmed.length > 1 ? "s" : ""} not bound: ${descriptions}`);
	}
	async listWorkflowHealth(workflowId) {
		const workflow = this.requireWorkflow(workflowId);
		const bindings = await this.credentialStore.listBindingsByWorkflowId(workflowId);
		const bindingsByKey = new Map(bindings.map((binding) => [this.toBindingKeyString(binding.key), binding]));
		const slots = [];
		for (const slotRef of this.workflowCredentialNodeResolver.listSlots(workflow)) {
			const requirement = slotRef.requirement;
			const bindingKey = {
				workflowId,
				nodeId: slotRef.nodeId,
				slotKey: requirement.slotKey
			};
			const binding = bindingsByKey.get(this.toBindingKeyString(bindingKey));
			if (!binding) {
				slots.push({
					workflowId,
					nodeId: slotRef.nodeId,
					nodeName: slotRef.nodeName,
					requirement,
					health: { status: requirement.optional ? "optional-unbound" : "unbound" }
				});
				continue;
			}
			const instance = await this.credentialInstanceService.requireInstance(binding.instanceId);
			const latestTestResult = await this.credentialStore.getLatestTestResult(instance.instanceId);
			slots.push({
				workflowId,
				nodeId: slotRef.nodeId,
				nodeName: slotRef.nodeName,
				requirement,
				instance: {
					instanceId: instance.instanceId,
					typeId: instance.typeId,
					displayName: instance.displayName,
					setupStatus: instance.setupStatus
				},
				health: {
					status: latestTestResult?.health.status ?? "unknown",
					message: latestTestResult?.health.message,
					testedAt: latestTestResult?.health.testedAt
				}
			});
		}
		return {
			workflowId,
			slots
		};
	}
	requireWorkflow(workflowId) {
		const workflow = this.workflowRepository.get(decodeURIComponent(workflowId));
		if (!workflow) throw new ApplicationRequestError(404, `Unknown workflowId: ${workflowId}`);
		return workflow;
	}
	requireRequirement(workflow, nodeId, slotKey) {
		const resolved = this.workflowCredentialNodeResolver.findRequirement(workflow, nodeId, slotKey);
		if (!resolved) {
			if (!this.workflowCredentialNodeResolver.isCredentialNodeIdInWorkflow(workflow, nodeId)) throw new ApplicationRequestError(404, `Unknown workflow node: ${nodeId}`);
			throw new ApplicationRequestError(400, `Node ${nodeId} does not declare credential slot ${slotKey}.`);
		}
		return resolved.requirement;
	}
	toBindingKeyString(bindingKey) {
		return `${bindingKey.workflowId}:${bindingKey.nodeId}:${bindingKey.slotKey}`;
	}
};
CredentialBindingService = __decorate([
	injectable(),
	__decorateParam(0, inject(ApplicationTokens.CredentialStore)),
	__decorateParam(1, inject(CredentialInstanceService)),
	__decorateParam(2, inject(CoreTokens.WorkflowRepository)),
	__decorateParam(3, inject(CoreTokens.CredentialSessionService)),
	__decorateParam(4, inject(WorkflowCredentialNodeResolver)),
	__decorateParam(5, inject(ApplicationTokens.LoggerFactory)),
	__decorateMetadata("design:paramtypes", [
		Object,
		typeof (_ref$3 = typeof CredentialInstanceService !== "undefined" && CredentialInstanceService) === "function" ? _ref$3 : Object,
		Object,
		Object,
		typeof (_ref2$3 = typeof WorkflowCredentialNodeResolver !== "undefined" && WorkflowCredentialNodeResolver) === "function" ? _ref2$3 : Object,
		Object
	])
], CredentialBindingService);

//#endregion
//#region src/domain/credentials/CredentialRuntimeMaterialService.ts
var _ref$2, _ref2$2, _ref3$2;
let CredentialRuntimeMaterialService = class CredentialRuntimeMaterialService$1 {
	constructor(credentialStore, credentialMaterialResolver, credentialSecretCipher, credentialTypeRegistry) {
		this.credentialStore = credentialStore;
		this.credentialMaterialResolver = credentialMaterialResolver;
		this.credentialSecretCipher = credentialSecretCipher;
		this.credentialTypeRegistry = credentialTypeRegistry;
	}
	async compose(instance) {
		const baseMaterial = await this.credentialMaterialResolver.resolveMaterial(instance);
		if ((this.credentialTypeRegistry.getCredentialType(instance.typeId)?.definition.auth)?.kind !== "oauth2") return baseMaterial;
		const oauth2Material = await this.credentialStore.getOAuth2Material(instance.instanceId);
		if (!oauth2Material) return baseMaterial;
		const decryptedOauth2Material = this.credentialSecretCipher.decrypt(oauth2Material);
		return Object.freeze({
			...baseMaterial,
			...decryptedOauth2Material
		});
	}
};
CredentialRuntimeMaterialService = __decorate([
	injectable(),
	__decorateParam(0, inject(ApplicationTokens.CredentialStore)),
	__decorateParam(1, inject(CredentialMaterialResolver)),
	__decorateParam(2, inject(CredentialSecretCipher)),
	__decorateParam(3, inject(CredentialTypeRegistryImpl)),
	__decorateMetadata("design:paramtypes", [
		Object,
		typeof (_ref$2 = typeof CredentialMaterialResolver !== "undefined" && CredentialMaterialResolver) === "function" ? _ref$2 : Object,
		typeof (_ref2$2 = typeof CredentialSecretCipher !== "undefined" && CredentialSecretCipher) === "function" ? _ref2$2 : Object,
		typeof (_ref3$2 = typeof CredentialTypeRegistryImpl !== "undefined" && CredentialTypeRegistryImpl) === "function" ? _ref3$2 : Object
	])
], CredentialRuntimeMaterialService);

//#endregion
//#region src/domain/credentials/CredentialSessionServiceImpl.ts
var _ref$1, _ref2$1, _ref3$1, _ref4$1;
let CredentialSessionServiceImpl = class CredentialSessionServiceImpl$1 {
	cachedSessionsByInstanceId = /* @__PURE__ */ new Map();
	cachedInstanceIdsByBindingKey = /* @__PURE__ */ new Map();
	constructor(credentialStore, credentialRuntimeMaterialService, credentialFieldEnvOverlayService, credentialTypeRegistry, workflowRepository, workflowCredentialNodeResolver) {
		this.credentialStore = credentialStore;
		this.credentialRuntimeMaterialService = credentialRuntimeMaterialService;
		this.credentialFieldEnvOverlayService = credentialFieldEnvOverlayService;
		this.credentialTypeRegistry = credentialTypeRegistry;
		this.workflowRepository = workflowRepository;
		this.workflowCredentialNodeResolver = workflowCredentialNodeResolver;
	}
	async getSession(args) {
		const workflow = this.workflowRepository.get(decodeURIComponent(args.workflowId));
		const displayLabel = workflow ? this.workflowCredentialNodeResolver.describeCredentialNodeDisplay(workflow, args.nodeId) : void 0;
		const requirement = workflow ? this.workflowCredentialNodeResolver.findRequirement(workflow, args.nodeId, args.slotKey)?.requirement : void 0;
		const bindingKey = {
			workflowId: args.workflowId,
			nodeId: args.nodeId,
			slotKey: args.slotKey
		};
		const binding = await this.credentialStore.getBinding(bindingKey);
		if (!binding) {
			const unbound = new CredentialUnboundError(bindingKey, requirement?.acceptedTypes ?? []);
			if (displayLabel) throw new Error(`${displayLabel}: ${unbound.message}`, { cause: unbound });
			throw unbound;
		}
		const bindingCacheKey = this.toBindingKeyString(bindingKey);
		this.cachedInstanceIdsByBindingKey.set(bindingCacheKey, binding.instanceId);
		const cachedSession = this.cachedSessionsByInstanceId.get(binding.instanceId);
		if (cachedSession) return await cachedSession;
		const nextSessionPromise = this.createSession(binding.instanceId, displayLabel).catch((error) => {
			this.cachedSessionsByInstanceId.delete(binding.instanceId);
			throw error;
		});
		this.cachedSessionsByInstanceId.set(binding.instanceId, nextSessionPromise);
		return await nextSessionPromise;
	}
	evictInstance(instanceId) {
		this.cachedSessionsByInstanceId.delete(instanceId);
	}
	evictBinding(bindingKey) {
		const cacheKey = this.toBindingKeyString(bindingKey);
		const instanceId = this.cachedInstanceIdsByBindingKey.get(cacheKey);
		if (instanceId) this.cachedSessionsByInstanceId.delete(instanceId);
		this.cachedInstanceIdsByBindingKey.delete(cacheKey);
	}
	async createSession(instanceId, displayLabel) {
		const instance = await this.credentialStore.getInstance(instanceId);
		if (!instance) throw new ApplicationRequestError(404, `Unknown credential instance: ${instanceId}`);
		const credentialType = this.credentialTypeRegistry.getCredentialType(instance.typeId);
		if (!credentialType) throw new ApplicationRequestError(400, `${displayLabel ? `${displayLabel}: ` : ""}Credential type "${instance.typeId}" is not registered in this runtime (binding points at an unknown type).`);
		const material = await this.credentialRuntimeMaterialService.compose(instance);
		const { resolvedPublicConfig, resolvedMaterial } = this.credentialFieldEnvOverlayService.apply({
			definition: credentialType.definition,
			publicConfig: instance.publicConfig,
			material
		});
		return await credentialType.createSession({
			instance,
			material: resolvedMaterial,
			publicConfig: resolvedPublicConfig
		});
	}
	toBindingKeyString(bindingKey) {
		return `${bindingKey.workflowId}:${bindingKey.nodeId}:${bindingKey.slotKey}`;
	}
};
CredentialSessionServiceImpl = __decorate([
	injectable(),
	__decorateParam(0, inject(ApplicationTokens.CredentialStore)),
	__decorateParam(1, inject(CredentialRuntimeMaterialService)),
	__decorateParam(2, inject(CredentialFieldEnvOverlayService)),
	__decorateParam(3, inject(CredentialTypeRegistryImpl)),
	__decorateParam(4, inject(CoreTokens.WorkflowRepository)),
	__decorateParam(5, inject(WorkflowCredentialNodeResolver)),
	__decorateMetadata("design:paramtypes", [
		Object,
		typeof (_ref$1 = typeof CredentialRuntimeMaterialService !== "undefined" && CredentialRuntimeMaterialService) === "function" ? _ref$1 : Object,
		typeof (_ref2$1 = typeof CredentialFieldEnvOverlayService !== "undefined" && CredentialFieldEnvOverlayService) === "function" ? _ref2$1 : Object,
		typeof (_ref3$1 = typeof CredentialTypeRegistryImpl !== "undefined" && CredentialTypeRegistryImpl) === "function" ? _ref3$1 : Object,
		Object,
		typeof (_ref4$1 = typeof WorkflowCredentialNodeResolver !== "undefined" && WorkflowCredentialNodeResolver) === "function" ? _ref4$1 : Object
	])
], CredentialSessionServiceImpl);

//#endregion
//#region src/domain/credentials/CredentialTestService.ts
var _ref, _ref2, _ref3, _ref4;
let CredentialTestService = class CredentialTestService$1 {
	constructor(credentialInstanceService, credentialRuntimeMaterialService, credentialFieldEnvOverlayService, credentialTypeRegistry, credentialStore, credentialSessionService) {
		this.credentialInstanceService = credentialInstanceService;
		this.credentialRuntimeMaterialService = credentialRuntimeMaterialService;
		this.credentialFieldEnvOverlayService = credentialFieldEnvOverlayService;
		this.credentialTypeRegistry = credentialTypeRegistry;
		this.credentialStore = credentialStore;
		this.credentialSessionService = credentialSessionService;
	}
	async test(instanceId) {
		const instance = await this.credentialInstanceService.requireInstance(instanceId);
		const credentialType = this.requireCredentialType(instance.typeId);
		const material = await this.credentialRuntimeMaterialService.compose(instance);
		const { resolvedPublicConfig, resolvedMaterial } = this.credentialFieldEnvOverlayService.apply({
			definition: credentialType.definition,
			publicConfig: instance.publicConfig,
			material
		});
		const health = await credentialType.test({
			instance,
			material: resolvedMaterial,
			publicConfig: resolvedPublicConfig
		});
		const testedAt = health.testedAt ?? (/* @__PURE__ */ new Date()).toISOString();
		await this.credentialStore.saveTestResult({
			testId: randomUUID(),
			instanceId,
			health: {
				...health,
				testedAt
			},
			testedAt,
			expiresAt: health.expiresAt
		});
		this.credentialSessionService.evictInstance(instanceId);
		return {
			...health,
			testedAt
		};
	}
	requireCredentialType(typeId) {
		const credentialType = this.credentialTypeRegistry.getCredentialType(typeId);
		if (!credentialType) throw new ApplicationRequestError(400, `Unknown credential type: ${typeId}`);
		return credentialType;
	}
};
CredentialTestService = __decorate([
	injectable(),
	__decorateParam(0, inject(CredentialInstanceService)),
	__decorateParam(1, inject(CredentialRuntimeMaterialService)),
	__decorateParam(2, inject(CredentialFieldEnvOverlayService)),
	__decorateParam(3, inject(CredentialTypeRegistryImpl)),
	__decorateParam(4, inject(ApplicationTokens.CredentialStore)),
	__decorateParam(5, inject(CoreTokens.CredentialSessionService)),
	__decorateMetadata("design:paramtypes", [
		typeof (_ref = typeof CredentialInstanceService !== "undefined" && CredentialInstanceService) === "function" ? _ref : Object,
		typeof (_ref2 = typeof CredentialRuntimeMaterialService !== "undefined" && CredentialRuntimeMaterialService) === "function" ? _ref2 : Object,
		typeof (_ref3 = typeof CredentialFieldEnvOverlayService !== "undefined" && CredentialFieldEnvOverlayService) === "function" ? _ref3 : Object,
		typeof (_ref4 = typeof CredentialTypeRegistryImpl !== "undefined" && CredentialTypeRegistryImpl) === "function" ? _ref4 : Object,
		Object,
		Object
	])
], CredentialTestService);

//#endregion
export { CredentialInstanceService as a, CredentialSecretCipher as c, McpServerCatalog as d, ApplicationRequestError as f, OpenAiApiKeyCredentialHealthTester as g, OpenAiApiKeyCredentialTypeFactory as h, CredentialBindingService as i, CredentialFieldEnvOverlayService as l, ApplicationTokens as m, CredentialSessionServiceImpl as n, CredentialOAuth2ScopeResolver as o, CredentialTypeRegistryImpl as p, CredentialRuntimeMaterialService as r, CredentialMaterialResolver as s, CredentialTestService as t, WorkflowCredentialNodeResolver as u };
//# sourceMappingURL=CredentialServices-Bios0dM8.js.map