UNPKG

@sellable/install

Version:

One-command installer for Sellable MCP in Claude Code, Codex, and Hermes

239 lines (229 loc) • 6.79 kB
const SAFE_ID = /^[A-Za-z0-9_.:-]{1,256}$/; const SHA256 = /^[a-f0-9]{64}$/; const RUNTIME_BINDING_V1_KEYS = Object.freeze([ "schemaVersion", "workspaceId", "agentId", "runtimeId", "profileId", "revisionId", "installationId", "teamId", "slackGeneration", "routeGeneration", "membershipGeneration", "serviceCredentialGeneration", "modelCredentialGeneration", "runtimeGeneration", "selectedChannelIds", "memberAllowlist", ]); export const ADMIN_RUNTIME_BINDING_V3_KEYS = Object.freeze([ "schemaVersion", "runtimeMode", "workspaceId", "agentId", "runtimeId", "profileId", "serviceCredentialGeneration", "runtimeGeneration", ]); export const RUNTIME_BINDING_V2_KEYS = Object.freeze([ "schemaVersion", "runtimeMode", "workspaceId", "agentId", "runtimeId", "profileId", "revisionId", "installationId", "teamId", "botUserId", "slackAppGeneration", "slackGeneration", "routeGeneration", "membershipGeneration", "serviceCredentialGeneration", "modelCredentialGeneration", "modelActivationId", "modelBundleGeneration", "modelPolicyHash", "apiServerKeyGeneration", "apiServerKeyFingerprint", "runtimeGeneration", "selectedChannelIds", "memberAllowlist", "accessPolicyHash", "runtimeDesiredHash", ]); export const FIXED_TURN_BINDING_KEYS = Object.freeze([ "workspaceId", "agentId", "runtimeId", "profileId", "revisionId", "installationId", "teamId", "slackGeneration", "routeGeneration", "membershipGeneration", "serviceCredentialGeneration", "modelCredentialGeneration", "runtimeGeneration", ]); function exactKeys(value, keys) { return Boolean( value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).sort().join("\0") === [...keys].sort().join("\0") ); } function validScope(values, { allowEmpty = false } = {}) { return Boolean( Array.isArray(values) && (allowEmpty || values.length >= 1) && values.length <= 256 && values.every( (value) => typeof value === "string" && SAFE_ID.test(value) ) && new Set(values).size === values.length ); } export function validateMcpRuntimeBinding(binding) { if ( exactKeys(binding, ADMIN_RUNTIME_BINDING_V3_KEYS) && binding.schemaVersion === "sellable-agent-mcp-runtime-binding/v3" ) { for (const key of [ "workspaceId", "agentId", "runtimeId", "profileId", ]) { if (typeof binding[key] !== "string" || !SAFE_ID.test(binding[key])) { return false; } } return Boolean( binding.runtimeMode === "native_admin" && Number.isSafeInteger(binding.serviceCredentialGeneration) && binding.serviceCredentialGeneration > 0 && Number.isSafeInteger(binding.runtimeGeneration) && binding.runtimeGeneration > 0 ); } if ( exactKeys(binding, RUNTIME_BINDING_V2_KEYS) && binding.schemaVersion === "sellable-agent-mcp-runtime-binding/v2" ) { for (const key of [ "workspaceId", "agentId", "runtimeId", "profileId", "revisionId", "installationId", "teamId", "botUserId", ]) { if (typeof binding[key] !== "string" || !SAFE_ID.test(binding[key])) { return false; } } for (const key of [ "slackAppGeneration", "slackGeneration", "routeGeneration", "membershipGeneration", "serviceCredentialGeneration", "modelCredentialGeneration", "modelBundleGeneration", "apiServerKeyGeneration", "runtimeGeneration", ]) { if (!Number.isSafeInteger(binding[key]) || binding[key] < 1) return false; } return Boolean( binding.runtimeMode === "native_slack_customer" && typeof binding.modelActivationId === "string" && SAFE_ID.test(binding.modelActivationId) && SHA256.test(binding.modelPolicyHash ?? "") && SHA256.test(binding.accessPolicyHash ?? "") && SHA256.test(binding.runtimeDesiredHash ?? "") && typeof binding.apiServerKeyFingerprint === "string" && validScope(binding.selectedChannelIds) && validScope(binding.memberAllowlist, { allowEmpty: true }) ); } if ( !exactKeys(binding, RUNTIME_BINDING_V1_KEYS) || binding.schemaVersion !== "sellable-agent-mcp-runtime-binding/v1" ) { return false; } for (const key of FIXED_TURN_BINDING_KEYS) { if (key.endsWith("Generation")) { if (!Number.isSafeInteger(binding[key]) || binding[key] < 1) return false; } else if ( typeof binding[key] !== "string" || !SAFE_ID.test(binding[key]) ) { return false; } } return ( validScope(binding.selectedChannelIds) && validScope(binding.memberAllowlist) ); } export function createMcpAdminRuntimeBindingV3(input) { const binding = { schemaVersion: "sellable-agent-mcp-runtime-binding/v3", runtimeMode: "native_admin", workspaceId: input.workspaceId, agentId: input.agentId, runtimeId: input.runtimeId, profileId: input.profileId, serviceCredentialGeneration: input.serviceCredentialGeneration, runtimeGeneration: input.runtimeGeneration, }; if (!validateMcpRuntimeBinding(binding)) { throw new Error("mcp_admin_runtime_binding_v3_invalid"); } return binding; } export function createMcpRuntimeBindingV2(desired) { const binding = { schemaVersion: "sellable-agent-mcp-runtime-binding/v2", runtimeMode: desired.runtimeMode, workspaceId: desired.workspaceId, agentId: desired.agentId, runtimeId: desired.runtimeId, profileId: desired.profileId, revisionId: desired.revisionId, installationId: desired.installationId, teamId: desired.teamId, botUserId: desired.botUserId, slackAppGeneration: desired.slackAppGeneration, slackGeneration: desired.slackGeneration, routeGeneration: desired.routeGeneration, membershipGeneration: desired.membershipGeneration, serviceCredentialGeneration: desired.serviceCredentialGeneration, modelCredentialGeneration: desired.modelCredentialGeneration, modelActivationId: desired.modelActivationId, modelBundleGeneration: desired.modelBundleGeneration, modelPolicyHash: desired.modelPolicyHash, apiServerKeyGeneration: desired.apiServerKeyGeneration, apiServerKeyFingerprint: desired.apiServerKeyFingerprint, runtimeGeneration: desired.runtimeGeneration, selectedChannelIds: [...desired.selectedChannelIds], memberAllowlist: [...desired.memberAllowlist], accessPolicyHash: desired.accessPolicyHash, runtimeDesiredHash: desired.runtimeDesiredHash, }; if (!validateMcpRuntimeBinding(binding)) { throw new Error("mcp_runtime_binding_v2_invalid"); } return binding; }