@agent-native/core 0.12.4 → 0.12.5
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/dist/agent/engine/builder-engine.d.ts +3 -2
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +28 -9
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/builtin.js +3 -3
- package/dist/agent/engine/builtin.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +14 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/composer/TiptapComposer.js +1 -1
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +4 -1
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +7 -1
- package/dist/extensions/store.js.map +1 -1
- package/dist/server/credential-provider.d.ts +3 -2
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +4 -3
- package/dist/server/credential-provider.js.map +1 -1
- package/docs/content/getting-started.md +26 -0
- package/docs/content/template-dispatch.md +17 -0
- package/docs/content/template-images.md +54 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/extensions/routes.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n setResponseHeader,\n type H3Event,\n} from \"h3\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport { getSession } from \"../server/auth.js\";\nimport { recordChange } from \"../server/poll.js\";\nimport {\n runWithRequestContext,\n getRequestOrgId,\n} from \"../server/request-context.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport { getDbExec, isPostgres } from \"../db/client.js\";\nimport {\n listExtensions,\n getExtension,\n createExtension,\n updateExtension,\n updateExtensionContent,\n deleteExtension,\n ensureExtensionsTables,\n} from \"./store.js\";\nimport { buildExtensionHtml, EXTENSION_IFRAME_CSP } from \"./html-shell.js\";\nimport { getThemeVars } from \"./theme.js\";\nimport {\n resolveKeyReferences,\n validateUrlAllowlist,\n getKeyAllowlist,\n} from \"../secrets/substitution.js\";\nimport {\n collectSecretValues,\n normalizeExtensionProxyMethod,\n readResponseTextWithLimit,\n redactSecrets,\n redactString,\n sanitizeOutboundHeaders,\n} from \"./proxy-security.js\";\nimport {\n createSsrfSafeDispatcher,\n isBlockedExtensionUrlWithDns,\n} from \"./url-safety.js\";\nimport { ForbiddenError, resolveAccess } from \"../sharing/access.js\";\n\nexport function createExtensionsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n const parts = pathname ? pathname.split(\"/\") : [];\n\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n }\n\n const orgCtx = await getOrgContext(event).catch(() => null);\n const userEmail = session.email;\n const orgId = orgCtx?.orgId ?? undefined;\n\n try {\n return await runWithRequestContext({ userEmail, orgId }, () =>\n dispatch(event, method, parts, userEmail),\n );\n } catch (err) {\n if (err instanceof ForbiddenError) {\n setResponseStatus(event, 403);\n return { error: err.message };\n }\n throw err;\n }\n });\n}\n\nasync function dispatch(\n event: H3Event,\n method: string,\n parts: string[],\n userEmail: string,\n): Promise<unknown> {\n // POST /sql/query — read-only SQL for extension iframes\n if (\n method === \"POST\" &&\n parts.length === 2 &&\n parts[0] === \"sql\" &&\n parts[1] === \"query\"\n ) {\n return handleSqlQuery(event);\n }\n\n // POST /sql/exec — write SQL for extension iframes\n if (\n method === \"POST\" &&\n parts.length === 2 &&\n parts[0] === \"sql\" &&\n parts[1] === \"exec\"\n ) {\n return handleSqlExec(event);\n }\n\n // GET /data/:extensionId/:collection — list items in a collection\n if (method === \"GET\" && parts.length === 3 && parts[0] === \"data\") {\n return handleExtensionDataList(event, parts[1], parts[2], userEmail);\n }\n\n // POST /data/:extensionId/:collection — create/upsert an item\n if (method === \"POST\" && parts.length === 3 && parts[0] === \"data\") {\n return handleExtensionDataUpsert(event, parts[1], parts[2], userEmail);\n }\n\n // DELETE /data/:extensionId/:collection/:itemId — delete an item\n if (method === \"DELETE\" && parts.length === 4 && parts[0] === \"data\") {\n return handleExtensionDataDelete(\n event,\n parts[1],\n parts[2],\n parts[3],\n userEmail,\n );\n }\n\n // POST /proxy\n if (method === \"POST\" && parts.length === 1 && parts[0] === \"proxy\") {\n return handleProxy(event, userEmail);\n }\n\n // GET / — list\n if (method === \"GET\" && parts.length === 0) {\n return listExtensions();\n }\n\n // POST / — create\n if (method === \"POST\" && parts.length === 0) {\n const body = await readBody(event);\n if (!body.name) {\n setResponseStatus(event, 400);\n return { error: \"name is required\" };\n }\n const extension = await createExtension(body);\n recordChange({ source: \"action\", type: \"change\" });\n setResponseStatus(event, 201);\n return extension;\n }\n\n // GET /:id/render\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"render\") {\n const access = await resolveAccess(\"extension\", parts[0]);\n const extension = access?.resource;\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n const search = event.url?.search || \"\";\n const isDark = search.includes(\"dark=1\") || search.includes(\"dark=true\");\n const themeVars = getThemeVars(isDark);\n // Compute viewer-vs-author binding so the iframe can warn when the\n // viewer is NOT the author. The role is plumbed through to gate\n // dangerous bridge helpers in iframe-bridge.ts (audit H4).\n const isAuthor = extension.ownerEmail === userEmail;\n\n const html = buildExtensionHtml(\n extension.content,\n themeVars,\n isDark,\n parts[0],\n {\n authorEmail: extension.ownerEmail,\n viewerEmail: userEmail,\n isAuthor,\n role: access.role,\n },\n );\n // Security headers per render. We set these explicitly here (rather than\n // rely on the global security-headers middleware) because:\n // - The global middleware sets X-Frame-Options: DENY which would break\n // the legitimate iframe usage of this route inside the app.\n // - frame-ancestors in the CSP must be set as an HTTP header to be\n // enforced; meta-CSP can't set it per spec.\n setResponseHeader(event, \"Content-Type\", \"text/html; charset=utf-8\");\n setResponseHeader(event, \"Content-Security-Policy\", EXTENSION_IFRAME_CSP);\n setResponseHeader(event, \"X-Frame-Options\", \"SAMEORIGIN\");\n setResponseHeader(event, \"X-Content-Type-Options\", \"nosniff\");\n setResponseHeader(event, \"Referrer-Policy\", \"no-referrer\");\n return html;\n }\n\n // GET /:id\n if (method === \"GET\" && parts.length === 1) {\n const extension = await getExtension(parts[0]);\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return extension;\n }\n\n // PUT /:id\n if (method === \"PUT\" && parts.length === 1) {\n const body = await readBody(event);\n const hasContentUpdate =\n body.content !== undefined || body.patches !== undefined;\n const hasMetaUpdate =\n body.name !== undefined ||\n body.description !== undefined ||\n body.icon !== undefined ||\n body.visibility !== undefined;\n\n let result = null;\n if (hasContentUpdate) {\n result = await updateExtensionContent(parts[0], {\n content: body.content,\n patches: body.patches,\n });\n }\n if (hasMetaUpdate) {\n result = await updateExtension(parts[0], body);\n }\n if (!hasContentUpdate && !hasMetaUpdate) {\n result = await getExtension(parts[0]);\n }\n if (!result) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n recordChange({ source: \"action\", type: \"change\" });\n return result;\n }\n\n // DELETE /:id\n if (method === \"DELETE\" && parts.length === 1) {\n const ok = await deleteExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n recordChange({ source: \"action\", type: \"change\" });\n return { ok: true };\n }\n\n setResponseStatus(event, 404);\n return { error: \"Not found\" };\n}\n\nasync function handleExtensionDataList(\n event: H3Event,\n extensionId: string,\n collection: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const extension = await getExtension(extensionId);\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n const client = getDbExec();\n const url = event.url;\n const limitParam = url?.searchParams?.get(\"limit\");\n const limit = limitParam\n ? Math.min(Math.max(1, Number(limitParam)), 1000)\n : 100;\n const scope = url?.searchParams?.get(\"scope\") || \"user\";\n const orgId = getRequestOrgId();\n\n if (scope === \"org\") {\n if (!orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ? AND scope = 'org' AND org_id = ?\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [extensionId, collection, orgId, limit],\n });\n return result.rows ?? [];\n }\n\n if (scope === \"all\") {\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ?\n AND ((scope = 'user' AND owner_email = ?) OR (scope = 'org' AND org_id = ?))\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [extensionId, collection, userEmail, orgId ?? \"\", limit],\n });\n return result.rows ?? [];\n }\n\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ? AND scope = 'user' AND owner_email = ?\n ORDER BY updated_at DESC\n LIMIT ?`,\n args: [extensionId, collection, userEmail, limit],\n });\n return result.rows ?? [];\n}\n\nasync function handleExtensionDataUpsert(\n event: H3Event,\n extensionId: string,\n collection: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const extension = await getExtension(extensionId);\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n const body = await readBody(event);\n if (body.data === undefined) {\n setResponseStatus(event, 400);\n return { error: \"data is required\" };\n }\n const itemId = String(body.id || randomUUID());\n const data =\n typeof body.data === \"string\" ? body.data : JSON.stringify(body.data);\n const now = new Date().toISOString();\n const scope = body.scope === \"org\" ? \"org\" : \"user\";\n const orgId = getRequestOrgId();\n\n if (scope === \"org\" && !orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n\n const scopeKey = scope === \"org\" ? `org:${orgId}` : userEmail;\n const client = getDbExec();\n const pg = isPostgres();\n const conflictClause = pg\n ? `ON CONFLICT (tool_id, collection, scope_key, item_id)\n DO UPDATE SET data = EXCLUDED.data, updated_at = EXCLUDED.updated_at`\n : `ON CONFLICT (tool_id, collection, scope_key, item_id)\n DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at`;\n\n await client.execute({\n sql: `INSERT INTO tool_data (id, tool_id, collection, item_id, data, owner_email, scope, org_id, scope_key, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ${conflictClause}`,\n args: [\n randomUUID(),\n extensionId,\n collection,\n itemId,\n data,\n userEmail,\n scope,\n scope === \"org\" ? orgId! : null,\n scopeKey,\n now,\n now,\n ],\n });\n return {\n id: itemId,\n extensionId,\n collection,\n data,\n ownerEmail: userEmail,\n scope,\n orgId: scope === \"org\" ? orgId : null,\n createdAt: now,\n updatedAt: now,\n };\n}\n\nasync function handleExtensionDataDelete(\n event: H3Event,\n extensionId: string,\n collection: string,\n itemId: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const extension = await getExtension(extensionId);\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n const url = event.url;\n const scope = url?.searchParams?.get(\"scope\") || \"user\";\n const orgId = getRequestOrgId();\n const client = getDbExec();\n\n if (scope === \"org\") {\n if (!orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n await client.execute({\n sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'org' AND org_id = ?`,\n args: [itemId, extensionId, collection, orgId],\n });\n return { ok: true };\n }\n\n await client.execute({\n sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'user' AND owner_email = ?`,\n args: [itemId, extensionId, collection, userEmail],\n });\n return { ok: true };\n}\n\nasync function handleProxy(\n event: H3Event,\n userEmail: string,\n): Promise<unknown> {\n const body = await readBody(event);\n const rawUrl = body.url;\n if (!rawUrl || typeof rawUrl !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"url is required\" };\n }\n\n const method = normalizeExtensionProxyMethod(body.method || \"GET\");\n if (!method) {\n setResponseStatus(event, 405);\n return {\n error:\n \"Unsupported HTTP method. Allowed methods: GET, POST, PUT, PATCH, DELETE, HEAD.\",\n };\n }\n const rawHeaders: Record<string, string> = body.headers || {};\n const rawBody = body.body;\n\n let resolvedUrl = rawUrl;\n let resolvedHeaders = JSON.stringify(rawHeaders);\n let resolvedBody = rawBody;\n const allUsedKeys: string[] = [];\n const allSecretValues: string[] = [];\n\n try {\n const urlResult = await resolveKeyReferences(rawUrl, \"user\", userEmail);\n resolvedUrl = urlResult.resolved;\n allUsedKeys.push(...urlResult.usedKeys);\n allSecretValues.push(...urlResult.secretValues);\n\n const headerResult = await resolveKeyReferences(\n resolvedHeaders,\n \"user\",\n userEmail,\n );\n resolvedHeaders = headerResult.resolved;\n allUsedKeys.push(...headerResult.usedKeys);\n allSecretValues.push(...headerResult.secretValues);\n\n if (rawBody) {\n const bodyResult = await resolveKeyReferences(\n typeof rawBody === \"string\" ? rawBody : JSON.stringify(rawBody),\n \"user\",\n userEmail,\n );\n resolvedBody = bodyResult.resolved;\n allUsedKeys.push(...bodyResult.usedKeys);\n allSecretValues.push(...bodyResult.secretValues);\n }\n } catch (err: any) {\n setResponseStatus(event, 400);\n return { error: `Key resolution failed: ${err?.message ?? err}` };\n }\n const secretValues = collectSecretValues(allSecretValues);\n\n if (await isBlockedExtensionUrlWithDns(resolvedUrl)) {\n setResponseStatus(event, 403);\n return { error: \"Requests to private/internal addresses are not allowed\" };\n }\n\n for (const keyName of new Set(allUsedKeys)) {\n const allowlist = await getKeyAllowlist(keyName, \"user\", userEmail);\n if (!validateUrlAllowlist(resolvedUrl, allowlist)) {\n setResponseStatus(event, 403);\n return {\n error: `Key \"${keyName}\" is not allowed for this URL origin`,\n };\n }\n }\n\n let headers: Record<string, string>;\n try {\n headers = sanitizeOutboundHeaders(JSON.parse(resolvedHeaders));\n } catch {\n headers = sanitizeOutboundHeaders(rawHeaders);\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 15_000);\n\n // Best-effort connect-time SSRF guard. When undici is available (it ships\n // with Node 18+ but is not always exposed as an importable module), the\n // dispatcher re-checks the resolved IP at TCP-connect time, closing the\n // TOCTOU between the pre-flight `isBlockedExtensionUrlWithDns` lookup and the\n // actual fetch lookup. If undici is not importable, fall through to plain\n // fetch — the pre-flight remains the primary protection.\n const dispatcher = (await createSsrfSafeDispatcher()) ?? undefined;\n\n try {\n const fetchOpts: RequestInit & { dispatcher?: unknown } = {\n method,\n headers,\n signal: controller.signal,\n redirect: \"manual\",\n };\n if (dispatcher) fetchOpts.dispatcher = dispatcher;\n if (resolvedBody && [\"POST\", \"PUT\", \"PATCH\"].includes(method)) {\n const isStringBody = typeof resolvedBody === \"string\";\n fetchOpts.body = isStringBody\n ? resolvedBody\n : JSON.stringify(resolvedBody);\n // Only inject Content-Type when (a) the caller didn't set one and\n // (b) the body is actually JSON-shaped (object or stringified JSON).\n // Otherwise leave it unset so the runtime fetch picks an appropriate\n // default and we don't misrepresent text/plain bodies as JSON.\n const hasContentType = Object.keys(headers).some(\n (k) => k.toLowerCase() === \"content-type\",\n );\n if (!hasContentType) {\n const isJsonShaped =\n !isStringBody ||\n (typeof resolvedBody === \"string\" &&\n /^\\s*[{[]/.test(resolvedBody) &&\n isLikelyJson(resolvedBody));\n if (isJsonShaped) headers[\"Content-Type\"] = \"application/json\";\n }\n }\n\n const response = await fetch(resolvedUrl, fetchOpts);\n\n if (response.status >= 300 && response.status < 400) {\n const location = response.headers.get(\"location\");\n const redirectUrl = location ? new URL(location, resolvedUrl).href : null;\n if (redirectUrl && (await isBlockedExtensionUrlWithDns(redirectUrl))) {\n setResponseStatus(event, 403);\n return { error: \"Redirect to private/internal address blocked\" };\n }\n if (redirectUrl) {\n for (const keyName of new Set(allUsedKeys)) {\n const allowlist = await getKeyAllowlist(keyName, \"user\", userEmail);\n if (!validateUrlAllowlist(redirectUrl, allowlist)) {\n setResponseStatus(event, 403);\n return {\n error: `Redirect URL is not allowed for key \"${keyName}\"`,\n };\n }\n }\n }\n return {\n status: response.status,\n body: {\n redirect: redirectUrl\n ? redactString(redirectUrl, secretValues)\n : location,\n },\n };\n }\n\n const { text } = await readResponseTextWithLimit(response);\n let responseBody: unknown;\n try {\n responseBody = JSON.parse(text);\n } catch {\n responseBody = text;\n }\n\n return {\n status: response.status,\n body: redactSecrets(responseBody, secretValues),\n };\n } catch (err: any) {\n if (err?.name === \"AbortError\") {\n setResponseStatus(event, 504);\n return { error: \"Upstream request timed out\" };\n }\n setResponseStatus(event, 502);\n return {\n error: `Proxy request failed: ${redactSecrets(\n err?.message ?? String(err),\n secretValues,\n )}`,\n };\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * Capture console output from a CLI script that uses console.log for results.\n * Same technique as wrapCliScript in agent-chat-plugin.ts.\n */\nlet captureCliOutputQueue: Promise<void> = Promise.resolve();\n\nasync function captureCliOutput(\n fn: (args: string[]) => Promise<void>,\n args: string[],\n): Promise<string> {\n const previousCapture = captureCliOutputQueue;\n let releaseCapture!: () => void;\n captureCliOutputQueue = new Promise<void>((resolve) => {\n releaseCapture = resolve;\n });\n await previousCapture;\n\n const logs: string[] = [];\n const origLog = console.log;\n const origError = console.error;\n const origStdoutWrite = process.stdout.write;\n console.log = (...a: unknown[]) => {\n logs.push(a.map(String).join(\" \"));\n };\n console.error = (...a: unknown[]) => {\n logs.push(a.map(String).join(\" \"));\n };\n process.stdout.write = ((chunk: any) => {\n if (typeof chunk === \"string\") logs.push(chunk);\n else if (Buffer.isBuffer(chunk)) logs.push(chunk.toString());\n return true;\n }) as any;\n try {\n await fn(args);\n } catch (err: any) {\n logs.push(`Error: ${err?.message ?? String(err)}`);\n } finally {\n console.log = origLog;\n console.error = origError;\n process.stdout.write = origStdoutWrite;\n releaseCapture();\n }\n return logs.join(\"\\n\") || \"(no output)\";\n}\n\nasync function handleSqlQuery(event: H3Event): Promise<unknown> {\n const body = await readBody(event);\n const sql = body.sql;\n if (!sql || typeof sql !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"sql is required\" };\n }\n\n const cleanSql = stripSqlComments(sql);\n if (!/^\\s*(SELECT|WITH)\\b/i.test(cleanSql)) {\n setResponseStatus(event, 403);\n return { error: \"Only SELECT queries are allowed from extensions\" };\n }\n if (SENSITIVE_SQL_RE.test(cleanSql)) {\n setResponseStatus(event, 403);\n return {\n error: \"Sensitive framework tables are not readable from extensions\",\n };\n }\n\n try {\n const mod = await import(\"../scripts/db/query.js\");\n const args = [\"--sql\", sql, \"--format\", \"json\"];\n if (body.limit) args.push(\"--limit\", String(body.limit));\n if (body.args !== undefined) {\n if (!Array.isArray(body.args)) {\n setResponseStatus(event, 400);\n return { error: \"args must be an array\" };\n }\n args.push(\"--args\", JSON.stringify(body.args));\n }\n const output = await captureCliOutput(mod.default, args);\n try {\n return JSON.parse(output);\n } catch {\n return { output };\n }\n } catch (err: any) {\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"Query failed\" };\n }\n}\n\n// TODO(security): replace this regex blocklist with a SQL parser + an explicit\n// allowlist of tables a extension may read/write (e.g. only `tool_data`, plus a\n// per-template list). The current blocklist is best-effort defense in depth\n// and is by design bypassable via SQL constructions that don't include the\n// blocklisted token literally (string concat, dynamic SQL, etc). The temp-\n// view scoping in scripts/db/scoping.ts is the actual ownership boundary.\nconst DESTRUCTIVE_SQL_RE =\n /\\b(CREATE\\s+(?:(?:LOCAL|GLOBAL)\\s+)?(?:TEMPORARY|TEMP)?\\s*(TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|EXTENSION|ROLE|TABLESPACE|PUBLICATION|SUBSCRIPTION)|DROP\\s+(TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|EXTENSION|ROLE)|TRUNCATE|DELETE\\s+FROM\\s+(?!tool_data\\b)|ALTER\\s+(TABLE|VIEW|SCHEMA|DATABASE|FUNCTION|ROLE|EXTENSION|PUBLICATION)\\s+(?!tool_data\\b)|ATTACH|DETACH|VACUUM|REINDEX|PRAGMA|GRANT|REVOKE|SET\\s+ROLE|RESET\\s+ROLE|COPY)\\b/i;\n\n// Sensitive tables that extensions must not touch directly. Includes Better Auth\n// identity tables, framework infrastructure (tracing, evals, automations,\n// integrations, notifications, scheduling, sharing/orgs), and Postgres\n// catalogs that would let a extension enumerate or read internals.\nconst SENSITIVE_SQL_RE =\n /\\b(app_secrets|user|users|session|sessions|account|accounts|verification|oauth_tokens|tools|extensions|tool_shares|tool_slots|tool_slot_installs|tool_hidden_extensions|member|organization|invitation|jwks|agent_trace_spans|agent_trace_summaries|agent_feedback|agent_satisfaction_scores|agent_evals|agent_runs|agent_run_events|notifications|progress_runs|integration_configs|integration_pending_tasks|integration_thread_mappings|resources|org_members|org_invitations|bigquery_cache|dashboard_views|pg_catalog|information_schema|pg_class|pg_proc|pg_namespace|pg_user|pg_roles|pg_authid|pg_shadow)\\b/i;\n\n// Refuses positional INSERTs (no column list). `INSERT INTO recordings VALUES\n// (...)` would let a extension stuff arbitrary owner_email values into a row.\n// `INSERT INTO recordings (col1, col2) VALUES (...)` is required so the\n// downstream injectOwnership helper can append owner_email.\nconst POSITIONAL_INSERT_RE = /\\bINSERT\\s+INTO\\s+[\"'`]?\\w+[\"'`]?\\s+VALUES\\b/i;\n\nfunction stripSqlComments(sql: string): string {\n return sql.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/--[^\\n]*/g, \" \");\n}\n\nfunction isLikelyJson(text: string): boolean {\n try {\n const parsed = JSON.parse(text);\n return parsed !== null && typeof parsed === \"object\";\n } catch {\n return false;\n }\n}\n\nasync function handleSqlExec(event: H3Event): Promise<unknown> {\n const body = await readBody(event);\n const sql = body.sql;\n if (!sql || typeof sql !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"sql is required\" };\n }\n\n const cleanSql = stripSqlComments(sql);\n if (DESTRUCTIVE_SQL_RE.test(cleanSql)) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Schema changes and destructive SQL are not allowed from extensions\",\n };\n }\n if (SENSITIVE_SQL_RE.test(cleanSql)) {\n setResponseStatus(event, 403);\n return {\n error: \"Sensitive framework tables are not writable from extensions\",\n };\n }\n if (POSITIONAL_INSERT_RE.test(cleanSql)) {\n setResponseStatus(event, 400);\n return {\n error:\n \"INSERT must specify an explicit column list (e.g. INSERT INTO t (col1, col2) VALUES (?, ?)) so ownership can be injected.\",\n };\n }\n\n try {\n const mod = await import(\"../scripts/db/exec.js\");\n const args = [\"--sql\", sql, \"--format\", \"json\"];\n if (body.args !== undefined) {\n if (!Array.isArray(body.args)) {\n setResponseStatus(event, 400);\n return { error: \"args must be an array\" };\n }\n args.push(\"--args\", JSON.stringify(body.args));\n }\n const output = await captureCliOutput(mod.default, args);\n try {\n return JSON.parse(output);\n } catch {\n return { output };\n }\n } catch (err: any) {\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"Exec failed\" };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/extensions/routes.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n setResponseHeader,\n type H3Event,\n} from \"h3\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport { getSession } from \"../server/auth.js\";\nimport { recordChange } from \"../server/poll.js\";\nimport {\n runWithRequestContext,\n getRequestOrgId,\n} from \"../server/request-context.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport { getDbExec, isPostgres } from \"../db/client.js\";\nimport {\n listExtensions,\n getExtension,\n createExtension,\n updateExtension,\n updateExtensionContent,\n deleteExtension,\n ensureExtensionsTables,\n} from \"./store.js\";\nimport { buildExtensionHtml, EXTENSION_IFRAME_CSP } from \"./html-shell.js\";\nimport { getThemeVars } from \"./theme.js\";\nimport {\n resolveKeyReferences,\n validateUrlAllowlist,\n getKeyAllowlist,\n} from \"../secrets/substitution.js\";\nimport {\n collectSecretValues,\n normalizeExtensionProxyMethod,\n readResponseTextWithLimit,\n redactSecrets,\n redactString,\n sanitizeOutboundHeaders,\n} from \"./proxy-security.js\";\nimport {\n createSsrfSafeDispatcher,\n isBlockedExtensionUrlWithDns,\n} from \"./url-safety.js\";\nimport { ForbiddenError, resolveAccess } from \"../sharing/access.js\";\n\nexport function createExtensionsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n const parts = pathname ? pathname.split(\"/\") : [];\n\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n }\n\n const orgCtx = await getOrgContext(event).catch(() => null);\n const userEmail = session.email;\n const orgId = orgCtx?.orgId ?? undefined;\n\n try {\n return await runWithRequestContext({ userEmail, orgId }, async () => {\n await ensureExtensionsTables();\n return dispatch(event, method, parts, userEmail);\n });\n } catch (err) {\n if (err instanceof ForbiddenError) {\n setResponseStatus(event, 403);\n return { error: err.message };\n }\n throw err;\n }\n });\n}\n\nasync function dispatch(\n event: H3Event,\n method: string,\n parts: string[],\n userEmail: string,\n): Promise<unknown> {\n // POST /sql/query — read-only SQL for extension iframes\n if (\n method === \"POST\" &&\n parts.length === 2 &&\n parts[0] === \"sql\" &&\n parts[1] === \"query\"\n ) {\n return handleSqlQuery(event);\n }\n\n // POST /sql/exec — write SQL for extension iframes\n if (\n method === \"POST\" &&\n parts.length === 2 &&\n parts[0] === \"sql\" &&\n parts[1] === \"exec\"\n ) {\n return handleSqlExec(event);\n }\n\n // GET /data/:extensionId/:collection — list items in a collection\n if (method === \"GET\" && parts.length === 3 && parts[0] === \"data\") {\n return handleExtensionDataList(event, parts[1], parts[2], userEmail);\n }\n\n // POST /data/:extensionId/:collection — create/upsert an item\n if (method === \"POST\" && parts.length === 3 && parts[0] === \"data\") {\n return handleExtensionDataUpsert(event, parts[1], parts[2], userEmail);\n }\n\n // DELETE /data/:extensionId/:collection/:itemId — delete an item\n if (method === \"DELETE\" && parts.length === 4 && parts[0] === \"data\") {\n return handleExtensionDataDelete(\n event,\n parts[1],\n parts[2],\n parts[3],\n userEmail,\n );\n }\n\n // POST /proxy\n if (method === \"POST\" && parts.length === 1 && parts[0] === \"proxy\") {\n return handleProxy(event, userEmail);\n }\n\n // GET / — list\n if (method === \"GET\" && parts.length === 0) {\n return listExtensions();\n }\n\n // POST / — create\n if (method === \"POST\" && parts.length === 0) {\n const body = await readBody(event);\n if (!body.name) {\n setResponseStatus(event, 400);\n return { error: \"name is required\" };\n }\n const extension = await createExtension(body);\n recordChange({ source: \"action\", type: \"change\" });\n setResponseStatus(event, 201);\n return extension;\n }\n\n // GET /:id/render\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"render\") {\n const access = await resolveAccess(\"extension\", parts[0]);\n const extension = access?.resource;\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n const search = event.url?.search || \"\";\n const isDark = search.includes(\"dark=1\") || search.includes(\"dark=true\");\n const themeVars = getThemeVars(isDark);\n // Compute viewer-vs-author binding so the iframe can warn when the\n // viewer is NOT the author. The role is plumbed through to gate\n // dangerous bridge helpers in iframe-bridge.ts (audit H4).\n const isAuthor = extension.ownerEmail === userEmail;\n\n const html = buildExtensionHtml(\n extension.content,\n themeVars,\n isDark,\n parts[0],\n {\n authorEmail: extension.ownerEmail,\n viewerEmail: userEmail,\n isAuthor,\n role: access.role,\n },\n );\n // Security headers per render. We set these explicitly here (rather than\n // rely on the global security-headers middleware) because:\n // - The global middleware sets X-Frame-Options: DENY which would break\n // the legitimate iframe usage of this route inside the app.\n // - frame-ancestors in the CSP must be set as an HTTP header to be\n // enforced; meta-CSP can't set it per spec.\n setResponseHeader(event, \"Content-Type\", \"text/html; charset=utf-8\");\n setResponseHeader(event, \"Content-Security-Policy\", EXTENSION_IFRAME_CSP);\n setResponseHeader(event, \"X-Frame-Options\", \"SAMEORIGIN\");\n setResponseHeader(event, \"X-Content-Type-Options\", \"nosniff\");\n setResponseHeader(event, \"Referrer-Policy\", \"no-referrer\");\n return html;\n }\n\n // GET /:id\n if (method === \"GET\" && parts.length === 1) {\n const extension = await getExtension(parts[0]);\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return extension;\n }\n\n // PUT /:id\n if (method === \"PUT\" && parts.length === 1) {\n const body = await readBody(event);\n const hasContentUpdate =\n body.content !== undefined || body.patches !== undefined;\n const hasMetaUpdate =\n body.name !== undefined ||\n body.description !== undefined ||\n body.icon !== undefined ||\n body.visibility !== undefined;\n\n let result = null;\n if (hasContentUpdate) {\n result = await updateExtensionContent(parts[0], {\n content: body.content,\n patches: body.patches,\n });\n }\n if (hasMetaUpdate) {\n result = await updateExtension(parts[0], body);\n }\n if (!hasContentUpdate && !hasMetaUpdate) {\n result = await getExtension(parts[0]);\n }\n if (!result) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n recordChange({ source: \"action\", type: \"change\" });\n return result;\n }\n\n // DELETE /:id\n if (method === \"DELETE\" && parts.length === 1) {\n const ok = await deleteExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n recordChange({ source: \"action\", type: \"change\" });\n return { ok: true };\n }\n\n setResponseStatus(event, 404);\n return { error: \"Not found\" };\n}\n\nasync function handleExtensionDataList(\n event: H3Event,\n extensionId: string,\n collection: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const extension = await getExtension(extensionId);\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n const client = getDbExec();\n const url = event.url;\n const limitParam = url?.searchParams?.get(\"limit\");\n const limit = limitParam\n ? Math.min(Math.max(1, Number(limitParam)), 1000)\n : 100;\n const scope = url?.searchParams?.get(\"scope\") || \"user\";\n const orgId = getRequestOrgId();\n\n if (scope === \"org\") {\n if (!orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ? AND scope = 'org' AND org_id = ?\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [extensionId, collection, orgId, limit],\n });\n return result.rows ?? [];\n }\n\n if (scope === \"all\") {\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ?\n AND ((scope = 'user' AND owner_email = ?) OR (scope = 'org' AND org_id = ?))\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [extensionId, collection, userEmail, orgId ?? \"\", limit],\n });\n return result.rows ?? [];\n }\n\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ? AND scope = 'user' AND owner_email = ?\n ORDER BY updated_at DESC\n LIMIT ?`,\n args: [extensionId, collection, userEmail, limit],\n });\n return result.rows ?? [];\n}\n\nasync function handleExtensionDataUpsert(\n event: H3Event,\n extensionId: string,\n collection: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const extension = await getExtension(extensionId);\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n const body = await readBody(event);\n if (body.data === undefined) {\n setResponseStatus(event, 400);\n return { error: \"data is required\" };\n }\n const itemId = String(body.id || randomUUID());\n const data =\n typeof body.data === \"string\" ? body.data : JSON.stringify(body.data);\n const now = new Date().toISOString();\n const scope = body.scope === \"org\" ? \"org\" : \"user\";\n const orgId = getRequestOrgId();\n\n if (scope === \"org\" && !orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n\n const scopeKey = scope === \"org\" ? `org:${orgId}` : userEmail;\n const client = getDbExec();\n const pg = isPostgres();\n const conflictClause = pg\n ? `ON CONFLICT (tool_id, collection, scope_key, item_id)\n DO UPDATE SET data = EXCLUDED.data, updated_at = EXCLUDED.updated_at`\n : `ON CONFLICT (tool_id, collection, scope_key, item_id)\n DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at`;\n\n await client.execute({\n sql: `INSERT INTO tool_data (id, tool_id, collection, item_id, data, owner_email, scope, org_id, scope_key, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ${conflictClause}`,\n args: [\n randomUUID(),\n extensionId,\n collection,\n itemId,\n data,\n userEmail,\n scope,\n scope === \"org\" ? orgId! : null,\n scopeKey,\n now,\n now,\n ],\n });\n return {\n id: itemId,\n extensionId,\n collection,\n data,\n ownerEmail: userEmail,\n scope,\n orgId: scope === \"org\" ? orgId : null,\n createdAt: now,\n updatedAt: now,\n };\n}\n\nasync function handleExtensionDataDelete(\n event: H3Event,\n extensionId: string,\n collection: string,\n itemId: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const extension = await getExtension(extensionId);\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n const url = event.url;\n const scope = url?.searchParams?.get(\"scope\") || \"user\";\n const orgId = getRequestOrgId();\n const client = getDbExec();\n\n if (scope === \"org\") {\n if (!orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n await client.execute({\n sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'org' AND org_id = ?`,\n args: [itemId, extensionId, collection, orgId],\n });\n return { ok: true };\n }\n\n await client.execute({\n sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'user' AND owner_email = ?`,\n args: [itemId, extensionId, collection, userEmail],\n });\n return { ok: true };\n}\n\nasync function handleProxy(\n event: H3Event,\n userEmail: string,\n): Promise<unknown> {\n const body = await readBody(event);\n const rawUrl = body.url;\n if (!rawUrl || typeof rawUrl !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"url is required\" };\n }\n\n const method = normalizeExtensionProxyMethod(body.method || \"GET\");\n if (!method) {\n setResponseStatus(event, 405);\n return {\n error:\n \"Unsupported HTTP method. Allowed methods: GET, POST, PUT, PATCH, DELETE, HEAD.\",\n };\n }\n const rawHeaders: Record<string, string> = body.headers || {};\n const rawBody = body.body;\n\n let resolvedUrl = rawUrl;\n let resolvedHeaders = JSON.stringify(rawHeaders);\n let resolvedBody = rawBody;\n const allUsedKeys: string[] = [];\n const allSecretValues: string[] = [];\n\n try {\n const urlResult = await resolveKeyReferences(rawUrl, \"user\", userEmail);\n resolvedUrl = urlResult.resolved;\n allUsedKeys.push(...urlResult.usedKeys);\n allSecretValues.push(...urlResult.secretValues);\n\n const headerResult = await resolveKeyReferences(\n resolvedHeaders,\n \"user\",\n userEmail,\n );\n resolvedHeaders = headerResult.resolved;\n allUsedKeys.push(...headerResult.usedKeys);\n allSecretValues.push(...headerResult.secretValues);\n\n if (rawBody) {\n const bodyResult = await resolveKeyReferences(\n typeof rawBody === \"string\" ? rawBody : JSON.stringify(rawBody),\n \"user\",\n userEmail,\n );\n resolvedBody = bodyResult.resolved;\n allUsedKeys.push(...bodyResult.usedKeys);\n allSecretValues.push(...bodyResult.secretValues);\n }\n } catch (err: any) {\n setResponseStatus(event, 400);\n return { error: `Key resolution failed: ${err?.message ?? err}` };\n }\n const secretValues = collectSecretValues(allSecretValues);\n\n if (await isBlockedExtensionUrlWithDns(resolvedUrl)) {\n setResponseStatus(event, 403);\n return { error: \"Requests to private/internal addresses are not allowed\" };\n }\n\n for (const keyName of new Set(allUsedKeys)) {\n const allowlist = await getKeyAllowlist(keyName, \"user\", userEmail);\n if (!validateUrlAllowlist(resolvedUrl, allowlist)) {\n setResponseStatus(event, 403);\n return {\n error: `Key \"${keyName}\" is not allowed for this URL origin`,\n };\n }\n }\n\n let headers: Record<string, string>;\n try {\n headers = sanitizeOutboundHeaders(JSON.parse(resolvedHeaders));\n } catch {\n headers = sanitizeOutboundHeaders(rawHeaders);\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 15_000);\n\n // Best-effort connect-time SSRF guard. When undici is available (it ships\n // with Node 18+ but is not always exposed as an importable module), the\n // dispatcher re-checks the resolved IP at TCP-connect time, closing the\n // TOCTOU between the pre-flight `isBlockedExtensionUrlWithDns` lookup and the\n // actual fetch lookup. If undici is not importable, fall through to plain\n // fetch — the pre-flight remains the primary protection.\n const dispatcher = (await createSsrfSafeDispatcher()) ?? undefined;\n\n try {\n const fetchOpts: RequestInit & { dispatcher?: unknown } = {\n method,\n headers,\n signal: controller.signal,\n redirect: \"manual\",\n };\n if (dispatcher) fetchOpts.dispatcher = dispatcher;\n if (resolvedBody && [\"POST\", \"PUT\", \"PATCH\"].includes(method)) {\n const isStringBody = typeof resolvedBody === \"string\";\n fetchOpts.body = isStringBody\n ? resolvedBody\n : JSON.stringify(resolvedBody);\n // Only inject Content-Type when (a) the caller didn't set one and\n // (b) the body is actually JSON-shaped (object or stringified JSON).\n // Otherwise leave it unset so the runtime fetch picks an appropriate\n // default and we don't misrepresent text/plain bodies as JSON.\n const hasContentType = Object.keys(headers).some(\n (k) => k.toLowerCase() === \"content-type\",\n );\n if (!hasContentType) {\n const isJsonShaped =\n !isStringBody ||\n (typeof resolvedBody === \"string\" &&\n /^\\s*[{[]/.test(resolvedBody) &&\n isLikelyJson(resolvedBody));\n if (isJsonShaped) headers[\"Content-Type\"] = \"application/json\";\n }\n }\n\n const response = await fetch(resolvedUrl, fetchOpts);\n\n if (response.status >= 300 && response.status < 400) {\n const location = response.headers.get(\"location\");\n const redirectUrl = location ? new URL(location, resolvedUrl).href : null;\n if (redirectUrl && (await isBlockedExtensionUrlWithDns(redirectUrl))) {\n setResponseStatus(event, 403);\n return { error: \"Redirect to private/internal address blocked\" };\n }\n if (redirectUrl) {\n for (const keyName of new Set(allUsedKeys)) {\n const allowlist = await getKeyAllowlist(keyName, \"user\", userEmail);\n if (!validateUrlAllowlist(redirectUrl, allowlist)) {\n setResponseStatus(event, 403);\n return {\n error: `Redirect URL is not allowed for key \"${keyName}\"`,\n };\n }\n }\n }\n return {\n status: response.status,\n body: {\n redirect: redirectUrl\n ? redactString(redirectUrl, secretValues)\n : location,\n },\n };\n }\n\n const { text } = await readResponseTextWithLimit(response);\n let responseBody: unknown;\n try {\n responseBody = JSON.parse(text);\n } catch {\n responseBody = text;\n }\n\n return {\n status: response.status,\n body: redactSecrets(responseBody, secretValues),\n };\n } catch (err: any) {\n if (err?.name === \"AbortError\") {\n setResponseStatus(event, 504);\n return { error: \"Upstream request timed out\" };\n }\n setResponseStatus(event, 502);\n return {\n error: `Proxy request failed: ${redactSecrets(\n err?.message ?? String(err),\n secretValues,\n )}`,\n };\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * Capture console output from a CLI script that uses console.log for results.\n * Same technique as wrapCliScript in agent-chat-plugin.ts.\n */\nlet captureCliOutputQueue: Promise<void> = Promise.resolve();\n\nasync function captureCliOutput(\n fn: (args: string[]) => Promise<void>,\n args: string[],\n): Promise<string> {\n const previousCapture = captureCliOutputQueue;\n let releaseCapture!: () => void;\n captureCliOutputQueue = new Promise<void>((resolve) => {\n releaseCapture = resolve;\n });\n await previousCapture;\n\n const logs: string[] = [];\n const origLog = console.log;\n const origError = console.error;\n const origStdoutWrite = process.stdout.write;\n console.log = (...a: unknown[]) => {\n logs.push(a.map(String).join(\" \"));\n };\n console.error = (...a: unknown[]) => {\n logs.push(a.map(String).join(\" \"));\n };\n process.stdout.write = ((chunk: any) => {\n if (typeof chunk === \"string\") logs.push(chunk);\n else if (Buffer.isBuffer(chunk)) logs.push(chunk.toString());\n return true;\n }) as any;\n try {\n await fn(args);\n } catch (err: any) {\n logs.push(`Error: ${err?.message ?? String(err)}`);\n } finally {\n console.log = origLog;\n console.error = origError;\n process.stdout.write = origStdoutWrite;\n releaseCapture();\n }\n return logs.join(\"\\n\") || \"(no output)\";\n}\n\nasync function handleSqlQuery(event: H3Event): Promise<unknown> {\n const body = await readBody(event);\n const sql = body.sql;\n if (!sql || typeof sql !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"sql is required\" };\n }\n\n const cleanSql = stripSqlComments(sql);\n if (!/^\\s*(SELECT|WITH)\\b/i.test(cleanSql)) {\n setResponseStatus(event, 403);\n return { error: \"Only SELECT queries are allowed from extensions\" };\n }\n if (SENSITIVE_SQL_RE.test(cleanSql)) {\n setResponseStatus(event, 403);\n return {\n error: \"Sensitive framework tables are not readable from extensions\",\n };\n }\n\n try {\n const mod = await import(\"../scripts/db/query.js\");\n const args = [\"--sql\", sql, \"--format\", \"json\"];\n if (body.limit) args.push(\"--limit\", String(body.limit));\n if (body.args !== undefined) {\n if (!Array.isArray(body.args)) {\n setResponseStatus(event, 400);\n return { error: \"args must be an array\" };\n }\n args.push(\"--args\", JSON.stringify(body.args));\n }\n const output = await captureCliOutput(mod.default, args);\n try {\n return JSON.parse(output);\n } catch {\n return { output };\n }\n } catch (err: any) {\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"Query failed\" };\n }\n}\n\n// TODO(security): replace this regex blocklist with a SQL parser + an explicit\n// allowlist of tables a extension may read/write (e.g. only `tool_data`, plus a\n// per-template list). The current blocklist is best-effort defense in depth\n// and is by design bypassable via SQL constructions that don't include the\n// blocklisted token literally (string concat, dynamic SQL, etc). The temp-\n// view scoping in scripts/db/scoping.ts is the actual ownership boundary.\nconst DESTRUCTIVE_SQL_RE =\n /\\b(CREATE\\s+(?:(?:LOCAL|GLOBAL)\\s+)?(?:TEMPORARY|TEMP)?\\s*(TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|EXTENSION|ROLE|TABLESPACE|PUBLICATION|SUBSCRIPTION)|DROP\\s+(TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|EXTENSION|ROLE)|TRUNCATE|DELETE\\s+FROM\\s+(?!tool_data\\b)|ALTER\\s+(TABLE|VIEW|SCHEMA|DATABASE|FUNCTION|ROLE|EXTENSION|PUBLICATION)\\s+(?!tool_data\\b)|ATTACH|DETACH|VACUUM|REINDEX|PRAGMA|GRANT|REVOKE|SET\\s+ROLE|RESET\\s+ROLE|COPY)\\b/i;\n\n// Sensitive tables that extensions must not touch directly. Includes Better Auth\n// identity tables, framework infrastructure (tracing, evals, automations,\n// integrations, notifications, scheduling, sharing/orgs), and Postgres\n// catalogs that would let a extension enumerate or read internals.\nconst SENSITIVE_SQL_RE =\n /\\b(app_secrets|user|users|session|sessions|account|accounts|verification|oauth_tokens|tools|extensions|tool_shares|tool_slots|tool_slot_installs|tool_hidden_extensions|member|organization|invitation|jwks|agent_trace_spans|agent_trace_summaries|agent_feedback|agent_satisfaction_scores|agent_evals|agent_runs|agent_run_events|notifications|progress_runs|integration_configs|integration_pending_tasks|integration_thread_mappings|resources|org_members|org_invitations|bigquery_cache|dashboard_views|pg_catalog|information_schema|pg_class|pg_proc|pg_namespace|pg_user|pg_roles|pg_authid|pg_shadow)\\b/i;\n\n// Refuses positional INSERTs (no column list). `INSERT INTO recordings VALUES\n// (...)` would let a extension stuff arbitrary owner_email values into a row.\n// `INSERT INTO recordings (col1, col2) VALUES (...)` is required so the\n// downstream injectOwnership helper can append owner_email.\nconst POSITIONAL_INSERT_RE = /\\bINSERT\\s+INTO\\s+[\"'`]?\\w+[\"'`]?\\s+VALUES\\b/i;\n\nfunction stripSqlComments(sql: string): string {\n return sql.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/--[^\\n]*/g, \" \");\n}\n\nfunction isLikelyJson(text: string): boolean {\n try {\n const parsed = JSON.parse(text);\n return parsed !== null && typeof parsed === \"object\";\n } catch {\n return false;\n }\n}\n\nasync function handleSqlExec(event: H3Event): Promise<unknown> {\n const body = await readBody(event);\n const sql = body.sql;\n if (!sql || typeof sql !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"sql is required\" };\n }\n\n const cleanSql = stripSqlComments(sql);\n if (DESTRUCTIVE_SQL_RE.test(cleanSql)) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Schema changes and destructive SQL are not allowed from extensions\",\n };\n }\n if (SENSITIVE_SQL_RE.test(cleanSql)) {\n setResponseStatus(event, 403);\n return {\n error: \"Sensitive framework tables are not writable from extensions\",\n };\n }\n if (POSITIONAL_INSERT_RE.test(cleanSql)) {\n setResponseStatus(event, 400);\n return {\n error:\n \"INSERT must specify an explicit column list (e.g. INSERT INTO t (col1, col2) VALUES (?, ?)) so ownership can be injected.\",\n };\n }\n\n try {\n const mod = await import(\"../scripts/db/exec.js\");\n const args = [\"--sql\", sql, \"--format\", \"json\"];\n if (body.args !== undefined) {\n if (!Array.isArray(body.args)) {\n setResponseStatus(event, 400);\n return { error: \"args must be an array\" };\n }\n args.push(\"--args\", JSON.stringify(body.args));\n }\n const output = await captureCliOutput(mod.default, args);\n try {\n return JSON.parse(output);\n } catch {\n return { output };\n }\n } catch (err: any) {\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"Exec failed\" };\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/extensions/store.ts"],"names":[],"mappings":"AA4CA,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/extensions/store.ts"],"names":[],"mappings":"AA4CA,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqE5D;AAwFD,wBAAgB,2BAA2B,SAS1C;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;CAC1C;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAsB,cAAc,CAClC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,YAAY,EAAE,CAAC,CAazB;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAI3E;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,YAAY,CAAC,CAsBvB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;CAC3C;AAED,wBAAsB,eAAe,CACnC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAc9B;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA4B9B;AAED,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBlE;AAED,wBAAsB,mCAAmC,IAAI,OAAO,CAClE,GAAG,CAAC,MAAM,CAAC,CACZ,CAWA;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAchE;AAED,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUlE"}
|
package/dist/extensions/store.js
CHANGED
|
@@ -38,7 +38,13 @@ export async function ensureExtensionsTables() {
|
|
|
38
38
|
await retryOnDdlRace(() => client.execute(EXTENSION_CONSENTS_VIEWER_INDEX_SQL));
|
|
39
39
|
})();
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
try {
|
|
42
|
+
await _initPromise;
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
_initPromise = undefined;
|
|
46
|
+
throw err;
|
|
47
|
+
}
|
|
42
48
|
}
|
|
43
49
|
async function migrateMisnamedExtensionsTable(client, pg) {
|
|
44
50
|
const sql = pg
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/extensions/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { eq } from \"drizzle-orm\";\nimport { getDbExec, isPostgres, retryOnDdlRace } from \"../db/client.js\";\nimport { createGetDb } from \"../db/create-get-db.js\";\nimport {\n accessFilter,\n assertAccess,\n resolveAccess,\n} from \"../sharing/access.js\";\nimport {\n getRequestUserEmail,\n getRequestOrgId,\n} from \"../server/request-context.js\";\nimport { registerShareableResource } from \"../sharing/registry.js\";\nimport {\n extensions,\n extensionHides,\n extensionShares,\n EXTENSIONS_CREATE_SQL,\n EXTENSIONS_CREATE_SQL_PG,\n EXTENSION_SHARES_CREATE_SQL,\n EXTENSION_SHARES_CREATE_SQL_PG,\n EXTENSION_DATA_CREATE_SQL,\n EXTENSION_DATA_CREATE_SQL_PG,\n EXTENSION_DATA_ITEM_INDEX_SQL,\n EXTENSION_DATA_ITEM_INDEX_SQL_PG,\n EXTENSION_DATA_DROP_OLD_INDEX_SQL,\n EXTENSION_DATA_DROP_OLD_INDEX_SQL_PG,\n EXTENSIONS_OWNER_INDEX_SQL,\n EXTENSIONS_ORG_INDEX_SQL,\n EXTENSION_SHARES_RESOURCE_INDEX_SQL,\n EXTENSION_HIDES_CREATE_SQL,\n EXTENSION_HIDES_CREATE_SQL_PG,\n EXTENSION_HIDES_UNIQUE_INDEX_SQL,\n EXTENSION_HIDES_OWNER_INDEX_SQL,\n EXTENSION_CONSENTS_CREATE_SQL,\n EXTENSION_CONSENTS_CREATE_SQL_PG,\n EXTENSION_CONSENTS_VIEWER_INDEX_SQL,\n} from \"./schema.js\";\n\nconst getDb = createGetDb({ extensions, extensionShares, extensionHides });\n\nlet _initPromise: Promise<void> | undefined;\n\nexport async function ensureExtensionsTables(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const pg = isPostgres();\n await retryOnDdlRace(() =>\n client.execute(pg ? EXTENSIONS_CREATE_SQL_PG : EXTENSIONS_CREATE_SQL),\n );\n await migrateMisnamedExtensionsTable(client, pg);\n await retryOnDdlRace(() =>\n client.execute(\n pg ? EXTENSION_SHARES_CREATE_SQL_PG : EXTENSION_SHARES_CREATE_SQL,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n pg ? EXTENSION_DATA_CREATE_SQL_PG : EXTENSION_DATA_CREATE_SQL,\n ),\n );\n await ensureExtensionDataItemId(client, pg);\n await ensureExtensionDataScope(client, pg);\n await client.execute(\n pg\n ? EXTENSION_DATA_DROP_OLD_INDEX_SQL_PG\n : EXTENSION_DATA_DROP_OLD_INDEX_SQL,\n );\n await retryOnDdlRace(() =>\n client.execute(\n pg ? EXTENSION_DATA_ITEM_INDEX_SQL_PG : EXTENSION_DATA_ITEM_INDEX_SQL,\n ),\n );\n await retryOnDdlRace(() => client.execute(EXTENSIONS_OWNER_INDEX_SQL));\n await retryOnDdlRace(() => client.execute(EXTENSIONS_ORG_INDEX_SQL));\n await retryOnDdlRace(() =>\n client.execute(EXTENSION_SHARES_RESOURCE_INDEX_SQL),\n );\n await retryOnDdlRace(() =>\n client.execute(\n pg ? EXTENSION_HIDES_CREATE_SQL_PG : EXTENSION_HIDES_CREATE_SQL,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(EXTENSION_HIDES_UNIQUE_INDEX_SQL),\n );\n await retryOnDdlRace(() =>\n client.execute(EXTENSION_HIDES_OWNER_INDEX_SQL),\n );\n // tool_consents was introduced for an audit-C1 per-viewer consent\n // gate that we removed once we settled on intra-org trust as the\n // baseline. The table is kept (additive — never drop) so deploys\n // that already created it stay healthy; the runtime consent code\n // is gone. Idempotent CREATE IF NOT EXISTS for fresh schemas.\n await retryOnDdlRace(() =>\n client.execute(\n pg ? EXTENSION_CONSENTS_CREATE_SQL_PG : EXTENSION_CONSENTS_CREATE_SQL,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(EXTENSION_CONSENTS_VIEWER_INDEX_SQL),\n );\n })();\n }\n return _initPromise;\n}\n\nasync function migrateMisnamedExtensionsTable(\n client: ReturnType<typeof getDbExec>,\n pg: boolean,\n): Promise<void> {\n const sql = pg\n ? `INSERT INTO tools (id, name, description, content, icon, created_at, updated_at, owner_email, org_id, visibility)\n SELECT id, name, description, content, icon, created_at, updated_at, owner_email, org_id, visibility\n FROM extensions\n ON CONFLICT (id) DO NOTHING`\n : `INSERT OR IGNORE INTO tools (id, name, description, content, icon, created_at, updated_at, owner_email, org_id, visibility)\n SELECT id, name, description, content, icon, created_at, updated_at, owner_email, org_id, visibility\n FROM extensions`;\n\n try {\n await client.execute(sql);\n } catch (err: any) {\n const message = String(err?.message ?? err).toLowerCase();\n if (\n message.includes(\"no such table: extensions\") ||\n message.includes('relation \"extensions\" does not exist') ||\n message.includes(\"relation extensions does not exist\")\n ) {\n return;\n }\n throw err;\n }\n}\n\nasync function ensureExtensionDataItemId(\n client: ReturnType<typeof getDbExec>,\n pg: boolean,\n): Promise<void> {\n if (pg) {\n await client.execute(\n `ALTER TABLE tool_data ADD COLUMN IF NOT EXISTS item_id TEXT`,\n );\n return;\n }\n\n // Keep this additive: legacy rows with item_id=id are still read correctly\n // through COALESCE(item_id, id), so SQLite never needs a table rebuild here.\n try {\n await client.execute(`ALTER TABLE tool_data ADD COLUMN item_id TEXT`);\n } catch (err: any) {\n if (\n !String(err?.message ?? err)\n .toLowerCase()\n .includes(\"duplicate\")\n ) {\n throw err;\n }\n }\n}\n\nasync function ensureExtensionDataScope(\n client: ReturnType<typeof getDbExec>,\n pg: boolean,\n): Promise<void> {\n const addCol = (name: string, def: string) => {\n if (pg) {\n return client.execute(\n `ALTER TABLE tool_data ADD COLUMN IF NOT EXISTS ${name} ${def}`,\n );\n }\n return client\n .execute(`ALTER TABLE tool_data ADD COLUMN ${name} ${def}`)\n .catch((err: any) => {\n if (\n !String(err?.message ?? err)\n .toLowerCase()\n .includes(\"duplicate\")\n )\n throw err;\n });\n };\n await addCol(\"scope\", \"TEXT NOT NULL DEFAULT 'user'\");\n await addCol(\"org_id\", \"TEXT\");\n await addCol(\"scope_key\", \"TEXT NOT NULL DEFAULT 'local@localhost'\");\n // One-time backfill migration: replaces the dev-mode DEFAULT scope_key\n // with each row's real owner_email. Not a per-request fallback.\n await client.execute(\n // guard:allow-localhost-fallback — one-time backfill migration replacing dev-mode default scope_key with the row's real owner_email\n `UPDATE tool_data SET scope_key = owner_email WHERE scope_key = 'local@localhost' AND owner_email != 'local@localhost'`,\n );\n}\n\nexport function registerExtensionsShareable() {\n registerShareableResource({\n type: \"extension\",\n resourceTable: extensions,\n sharesTable: extensionShares,\n displayName: \"Extension\",\n titleColumn: \"name\",\n getDb: () => getDb(),\n });\n}\n\nexport interface ExtensionRow {\n id: string;\n name: string;\n description: string;\n content: string;\n icon: string | null;\n createdAt: string;\n updatedAt: string;\n ownerEmail: string;\n orgId: string | null;\n visibility: \"private\" | \"org\" | \"public\";\n}\n\nexport interface ListExtensionsOptions {\n includeHidden?: boolean;\n}\n\nexport async function listExtensions(\n options: ListExtensionsOptions = {},\n): Promise<ExtensionRow[]> {\n await ensureExtensionsTables();\n const db = getDb();\n const rows = (await db\n .select()\n .from(extensions)\n .where(accessFilter(extensions, extensionShares))) as ExtensionRow[];\n\n if (options.includeHidden) return rows;\n\n const hiddenIds = await getHiddenExtensionIdsForCurrentUser();\n if (hiddenIds.size === 0) return rows;\n return rows.filter((row) => !hiddenIds.has(row.id));\n}\n\nexport async function getExtension(id: string): Promise<ExtensionRow | null> {\n await ensureExtensionsTables();\n const access = await resolveAccess(\"extension\", id);\n return (access?.resource as ExtensionRow | undefined) ?? null;\n}\n\nexport interface CreateExtensionData {\n name: string;\n description?: string;\n content?: string;\n icon?: string;\n}\n\nexport async function createExtension(\n data: CreateExtensionData,\n): Promise<ExtensionRow> {\n await ensureExtensionsTables();\n const db = getDb();\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n const orgId = getRequestOrgId();\n const id = randomUUID();\n const now = new Date().toISOString();\n const row: ExtensionRow = {\n id,\n name: data.name,\n description: data.description ?? \"\",\n content: data.content ?? \"\",\n icon: data.icon ?? null,\n createdAt: now,\n updatedAt: now,\n ownerEmail: userEmail,\n orgId: orgId ?? null,\n visibility: \"private\",\n };\n await db.insert(extensions).values(row);\n return row;\n}\n\nexport interface UpdateExtensionData {\n name?: string;\n description?: string;\n icon?: string;\n visibility?: \"private\" | \"org\" | \"public\";\n}\n\nexport async function updateExtension(\n id: string,\n data: UpdateExtensionData,\n): Promise<ExtensionRow | null> {\n await ensureExtensionsTables();\n await assertAccess(\"extension\", id, \"editor\");\n const db = getDb();\n const updates: Record<string, unknown> = {\n updatedAt: new Date().toISOString(),\n };\n if (data.name !== undefined) updates.name = data.name;\n if (data.description !== undefined) updates.description = data.description;\n if (data.icon !== undefined) updates.icon = data.icon;\n if (data.visibility !== undefined) updates.visibility = data.visibility;\n await db.update(extensions).set(updates).where(eq(extensions.id, id));\n const rows = await db.select().from(extensions).where(eq(extensions.id, id));\n return (rows[0] as ExtensionRow) ?? null;\n}\n\nexport interface UpdateExtensionContentOpts {\n content?: string;\n patches?: Array<{ find: string; replace: string }>;\n}\n\nexport async function updateExtensionContent(\n id: string,\n opts: UpdateExtensionContentOpts,\n): Promise<ExtensionRow | null> {\n await ensureExtensionsTables();\n await assertAccess(\"extension\", id, \"editor\");\n const db = getDb();\n\n let newContent: string;\n if (opts.content !== undefined) {\n newContent = opts.content;\n } else if (opts.patches) {\n const rows = await db\n .select()\n .from(extensions)\n .where(eq(extensions.id, id));\n if (!rows[0]) return null;\n newContent = (rows[0] as ExtensionRow).content;\n for (const patch of opts.patches) {\n newContent = newContent.replace(patch.find, patch.replace);\n }\n } else {\n return null;\n }\n\n await db\n .update(extensions)\n .set({ content: newContent, updatedAt: new Date().toISOString() })\n .where(eq(extensions.id, id));\n const rows = await db.select().from(extensions).where(eq(extensions.id, id));\n return (rows[0] as ExtensionRow) ?? null;\n}\n\nexport async function deleteExtension(id: string): Promise<boolean> {\n await ensureExtensionsTables();\n await assertAccess(\"extension\", id, \"admin\");\n const db = getDb();\n const rows = await db.select().from(extensions).where(eq(extensions.id, id));\n if (!rows[0]) return false;\n await db.delete(extensionShares).where(eq(extensionShares.resourceId, id));\n await db.delete(extensionHides).where(eq(extensionHides.extensionId, id));\n await getDbExec().execute({\n sql: `DELETE FROM tool_data WHERE tool_id = ?`,\n args: [id],\n });\n const { cascadeDeleteExtensionSlots } = await import(\"./slots/store.js\");\n await cascadeDeleteExtensionSlots(id);\n await db.delete(extensions).where(eq(extensions.id, id));\n return true;\n}\n\nexport async function getHiddenExtensionIdsForCurrentUser(): Promise<\n Set<string>\n> {\n await ensureExtensionsTables();\n const userEmail = getRequestUserEmail();\n if (!userEmail) return new Set();\n\n const db = getDb();\n const rows = await db\n .select({ extensionId: extensionHides.extensionId })\n .from(extensionHides)\n .where(eq(extensionHides.ownerEmail, userEmail));\n return new Set(rows.map((row) => row.extensionId));\n}\n\nexport async function hideExtension(id: string): Promise<boolean> {\n await ensureExtensionsTables();\n await assertAccess(\"extension\", id, \"viewer\");\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n\n const now = new Date().toISOString();\n await getDbExec().execute({\n sql: `INSERT INTO tool_hidden_extensions (id, tool_id, owner_email, created_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT (owner_email, tool_id) DO NOTHING`,\n args: [randomUUID(), id, userEmail, now],\n });\n return true;\n}\n\nexport async function unhideExtension(id: string): Promise<boolean> {\n await ensureExtensionsTables();\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n\n await getDbExec().execute({\n sql: `DELETE FROM tool_hidden_extensions WHERE tool_id = ? AND owner_email = ?`,\n args: [id, userEmail],\n });\n return true;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/extensions/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { eq } from \"drizzle-orm\";\nimport { getDbExec, isPostgres, retryOnDdlRace } from \"../db/client.js\";\nimport { createGetDb } from \"../db/create-get-db.js\";\nimport {\n accessFilter,\n assertAccess,\n resolveAccess,\n} from \"../sharing/access.js\";\nimport {\n getRequestUserEmail,\n getRequestOrgId,\n} from \"../server/request-context.js\";\nimport { registerShareableResource } from \"../sharing/registry.js\";\nimport {\n extensions,\n extensionHides,\n extensionShares,\n EXTENSIONS_CREATE_SQL,\n EXTENSIONS_CREATE_SQL_PG,\n EXTENSION_SHARES_CREATE_SQL,\n EXTENSION_SHARES_CREATE_SQL_PG,\n EXTENSION_DATA_CREATE_SQL,\n EXTENSION_DATA_CREATE_SQL_PG,\n EXTENSION_DATA_ITEM_INDEX_SQL,\n EXTENSION_DATA_ITEM_INDEX_SQL_PG,\n EXTENSION_DATA_DROP_OLD_INDEX_SQL,\n EXTENSION_DATA_DROP_OLD_INDEX_SQL_PG,\n EXTENSIONS_OWNER_INDEX_SQL,\n EXTENSIONS_ORG_INDEX_SQL,\n EXTENSION_SHARES_RESOURCE_INDEX_SQL,\n EXTENSION_HIDES_CREATE_SQL,\n EXTENSION_HIDES_CREATE_SQL_PG,\n EXTENSION_HIDES_UNIQUE_INDEX_SQL,\n EXTENSION_HIDES_OWNER_INDEX_SQL,\n EXTENSION_CONSENTS_CREATE_SQL,\n EXTENSION_CONSENTS_CREATE_SQL_PG,\n EXTENSION_CONSENTS_VIEWER_INDEX_SQL,\n} from \"./schema.js\";\n\nconst getDb = createGetDb({ extensions, extensionShares, extensionHides });\n\nlet _initPromise: Promise<void> | undefined;\n\nexport async function ensureExtensionsTables(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const pg = isPostgres();\n await retryOnDdlRace(() =>\n client.execute(pg ? EXTENSIONS_CREATE_SQL_PG : EXTENSIONS_CREATE_SQL),\n );\n await migrateMisnamedExtensionsTable(client, pg);\n await retryOnDdlRace(() =>\n client.execute(\n pg ? EXTENSION_SHARES_CREATE_SQL_PG : EXTENSION_SHARES_CREATE_SQL,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n pg ? EXTENSION_DATA_CREATE_SQL_PG : EXTENSION_DATA_CREATE_SQL,\n ),\n );\n await ensureExtensionDataItemId(client, pg);\n await ensureExtensionDataScope(client, pg);\n await client.execute(\n pg\n ? EXTENSION_DATA_DROP_OLD_INDEX_SQL_PG\n : EXTENSION_DATA_DROP_OLD_INDEX_SQL,\n );\n await retryOnDdlRace(() =>\n client.execute(\n pg ? EXTENSION_DATA_ITEM_INDEX_SQL_PG : EXTENSION_DATA_ITEM_INDEX_SQL,\n ),\n );\n await retryOnDdlRace(() => client.execute(EXTENSIONS_OWNER_INDEX_SQL));\n await retryOnDdlRace(() => client.execute(EXTENSIONS_ORG_INDEX_SQL));\n await retryOnDdlRace(() =>\n client.execute(EXTENSION_SHARES_RESOURCE_INDEX_SQL),\n );\n await retryOnDdlRace(() =>\n client.execute(\n pg ? EXTENSION_HIDES_CREATE_SQL_PG : EXTENSION_HIDES_CREATE_SQL,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(EXTENSION_HIDES_UNIQUE_INDEX_SQL),\n );\n await retryOnDdlRace(() =>\n client.execute(EXTENSION_HIDES_OWNER_INDEX_SQL),\n );\n // tool_consents was introduced for an audit-C1 per-viewer consent\n // gate that we removed once we settled on intra-org trust as the\n // baseline. The table is kept (additive — never drop) so deploys\n // that already created it stay healthy; the runtime consent code\n // is gone. Idempotent CREATE IF NOT EXISTS for fresh schemas.\n await retryOnDdlRace(() =>\n client.execute(\n pg ? EXTENSION_CONSENTS_CREATE_SQL_PG : EXTENSION_CONSENTS_CREATE_SQL,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(EXTENSION_CONSENTS_VIEWER_INDEX_SQL),\n );\n })();\n }\n\n try {\n await _initPromise;\n } catch (err) {\n _initPromise = undefined;\n throw err;\n }\n}\n\nasync function migrateMisnamedExtensionsTable(\n client: ReturnType<typeof getDbExec>,\n pg: boolean,\n): Promise<void> {\n const sql = pg\n ? `INSERT INTO tools (id, name, description, content, icon, created_at, updated_at, owner_email, org_id, visibility)\n SELECT id, name, description, content, icon, created_at, updated_at, owner_email, org_id, visibility\n FROM extensions\n ON CONFLICT (id) DO NOTHING`\n : `INSERT OR IGNORE INTO tools (id, name, description, content, icon, created_at, updated_at, owner_email, org_id, visibility)\n SELECT id, name, description, content, icon, created_at, updated_at, owner_email, org_id, visibility\n FROM extensions`;\n\n try {\n await client.execute(sql);\n } catch (err: any) {\n const message = String(err?.message ?? err).toLowerCase();\n if (\n message.includes(\"no such table: extensions\") ||\n message.includes('relation \"extensions\" does not exist') ||\n message.includes(\"relation extensions does not exist\")\n ) {\n return;\n }\n throw err;\n }\n}\n\nasync function ensureExtensionDataItemId(\n client: ReturnType<typeof getDbExec>,\n pg: boolean,\n): Promise<void> {\n if (pg) {\n await client.execute(\n `ALTER TABLE tool_data ADD COLUMN IF NOT EXISTS item_id TEXT`,\n );\n return;\n }\n\n // Keep this additive: legacy rows with item_id=id are still read correctly\n // through COALESCE(item_id, id), so SQLite never needs a table rebuild here.\n try {\n await client.execute(`ALTER TABLE tool_data ADD COLUMN item_id TEXT`);\n } catch (err: any) {\n if (\n !String(err?.message ?? err)\n .toLowerCase()\n .includes(\"duplicate\")\n ) {\n throw err;\n }\n }\n}\n\nasync function ensureExtensionDataScope(\n client: ReturnType<typeof getDbExec>,\n pg: boolean,\n): Promise<void> {\n const addCol = (name: string, def: string) => {\n if (pg) {\n return client.execute(\n `ALTER TABLE tool_data ADD COLUMN IF NOT EXISTS ${name} ${def}`,\n );\n }\n return client\n .execute(`ALTER TABLE tool_data ADD COLUMN ${name} ${def}`)\n .catch((err: any) => {\n if (\n !String(err?.message ?? err)\n .toLowerCase()\n .includes(\"duplicate\")\n )\n throw err;\n });\n };\n await addCol(\"scope\", \"TEXT NOT NULL DEFAULT 'user'\");\n await addCol(\"org_id\", \"TEXT\");\n await addCol(\"scope_key\", \"TEXT NOT NULL DEFAULT 'local@localhost'\");\n // One-time backfill migration: replaces the dev-mode DEFAULT scope_key\n // with each row's real owner_email. Not a per-request fallback.\n await client.execute(\n // guard:allow-localhost-fallback — one-time backfill migration replacing dev-mode default scope_key with the row's real owner_email\n `UPDATE tool_data SET scope_key = owner_email WHERE scope_key = 'local@localhost' AND owner_email != 'local@localhost'`,\n );\n}\n\nexport function registerExtensionsShareable() {\n registerShareableResource({\n type: \"extension\",\n resourceTable: extensions,\n sharesTable: extensionShares,\n displayName: \"Extension\",\n titleColumn: \"name\",\n getDb: () => getDb(),\n });\n}\n\nexport interface ExtensionRow {\n id: string;\n name: string;\n description: string;\n content: string;\n icon: string | null;\n createdAt: string;\n updatedAt: string;\n ownerEmail: string;\n orgId: string | null;\n visibility: \"private\" | \"org\" | \"public\";\n}\n\nexport interface ListExtensionsOptions {\n includeHidden?: boolean;\n}\n\nexport async function listExtensions(\n options: ListExtensionsOptions = {},\n): Promise<ExtensionRow[]> {\n await ensureExtensionsTables();\n const db = getDb();\n const rows = (await db\n .select()\n .from(extensions)\n .where(accessFilter(extensions, extensionShares))) as ExtensionRow[];\n\n if (options.includeHidden) return rows;\n\n const hiddenIds = await getHiddenExtensionIdsForCurrentUser();\n if (hiddenIds.size === 0) return rows;\n return rows.filter((row) => !hiddenIds.has(row.id));\n}\n\nexport async function getExtension(id: string): Promise<ExtensionRow | null> {\n await ensureExtensionsTables();\n const access = await resolveAccess(\"extension\", id);\n return (access?.resource as ExtensionRow | undefined) ?? null;\n}\n\nexport interface CreateExtensionData {\n name: string;\n description?: string;\n content?: string;\n icon?: string;\n}\n\nexport async function createExtension(\n data: CreateExtensionData,\n): Promise<ExtensionRow> {\n await ensureExtensionsTables();\n const db = getDb();\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n const orgId = getRequestOrgId();\n const id = randomUUID();\n const now = new Date().toISOString();\n const row: ExtensionRow = {\n id,\n name: data.name,\n description: data.description ?? \"\",\n content: data.content ?? \"\",\n icon: data.icon ?? null,\n createdAt: now,\n updatedAt: now,\n ownerEmail: userEmail,\n orgId: orgId ?? null,\n visibility: \"private\",\n };\n await db.insert(extensions).values(row);\n return row;\n}\n\nexport interface UpdateExtensionData {\n name?: string;\n description?: string;\n icon?: string;\n visibility?: \"private\" | \"org\" | \"public\";\n}\n\nexport async function updateExtension(\n id: string,\n data: UpdateExtensionData,\n): Promise<ExtensionRow | null> {\n await ensureExtensionsTables();\n await assertAccess(\"extension\", id, \"editor\");\n const db = getDb();\n const updates: Record<string, unknown> = {\n updatedAt: new Date().toISOString(),\n };\n if (data.name !== undefined) updates.name = data.name;\n if (data.description !== undefined) updates.description = data.description;\n if (data.icon !== undefined) updates.icon = data.icon;\n if (data.visibility !== undefined) updates.visibility = data.visibility;\n await db.update(extensions).set(updates).where(eq(extensions.id, id));\n const rows = await db.select().from(extensions).where(eq(extensions.id, id));\n return (rows[0] as ExtensionRow) ?? null;\n}\n\nexport interface UpdateExtensionContentOpts {\n content?: string;\n patches?: Array<{ find: string; replace: string }>;\n}\n\nexport async function updateExtensionContent(\n id: string,\n opts: UpdateExtensionContentOpts,\n): Promise<ExtensionRow | null> {\n await ensureExtensionsTables();\n await assertAccess(\"extension\", id, \"editor\");\n const db = getDb();\n\n let newContent: string;\n if (opts.content !== undefined) {\n newContent = opts.content;\n } else if (opts.patches) {\n const rows = await db\n .select()\n .from(extensions)\n .where(eq(extensions.id, id));\n if (!rows[0]) return null;\n newContent = (rows[0] as ExtensionRow).content;\n for (const patch of opts.patches) {\n newContent = newContent.replace(patch.find, patch.replace);\n }\n } else {\n return null;\n }\n\n await db\n .update(extensions)\n .set({ content: newContent, updatedAt: new Date().toISOString() })\n .where(eq(extensions.id, id));\n const rows = await db.select().from(extensions).where(eq(extensions.id, id));\n return (rows[0] as ExtensionRow) ?? null;\n}\n\nexport async function deleteExtension(id: string): Promise<boolean> {\n await ensureExtensionsTables();\n await assertAccess(\"extension\", id, \"admin\");\n const db = getDb();\n const rows = await db.select().from(extensions).where(eq(extensions.id, id));\n if (!rows[0]) return false;\n await db.delete(extensionShares).where(eq(extensionShares.resourceId, id));\n await db.delete(extensionHides).where(eq(extensionHides.extensionId, id));\n await getDbExec().execute({\n sql: `DELETE FROM tool_data WHERE tool_id = ?`,\n args: [id],\n });\n const { cascadeDeleteExtensionSlots } = await import(\"./slots/store.js\");\n await cascadeDeleteExtensionSlots(id);\n await db.delete(extensions).where(eq(extensions.id, id));\n return true;\n}\n\nexport async function getHiddenExtensionIdsForCurrentUser(): Promise<\n Set<string>\n> {\n await ensureExtensionsTables();\n const userEmail = getRequestUserEmail();\n if (!userEmail) return new Set();\n\n const db = getDb();\n const rows = await db\n .select({ extensionId: extensionHides.extensionId })\n .from(extensionHides)\n .where(eq(extensionHides.ownerEmail, userEmail));\n return new Set(rows.map((row) => row.extensionId));\n}\n\nexport async function hideExtension(id: string): Promise<boolean> {\n await ensureExtensionsTables();\n await assertAccess(\"extension\", id, \"viewer\");\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n\n const now = new Date().toISOString();\n await getDbExec().execute({\n sql: `INSERT INTO tool_hidden_extensions (id, tool_id, owner_email, created_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT (owner_email, tool_id) DO NOTHING`,\n args: [randomUUID(), id, userEmail, now],\n });\n return true;\n}\n\nexport async function unhideExtension(id: string): Promise<boolean> {\n await ensureExtensionsTables();\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n\n await getDbExec().execute({\n sql: `DELETE FROM tool_hidden_extensions WHERE tool_id = ? AND owner_email = ?`,\n args: [id, userEmail],\n });\n return true;\n}\n"]}
|
|
@@ -147,8 +147,9 @@ export declare function hasBuilderPrivateKey(): boolean;
|
|
|
147
147
|
export declare function getBuilderProxyOrigin(): string;
|
|
148
148
|
/**
|
|
149
149
|
* Base URL for the public Builder LLM gateway (distinct from the internal
|
|
150
|
-
* proxy origin above — the public gateway lives at
|
|
151
|
-
* while the internal origin is
|
|
150
|
+
* proxy origin above — the public gateway lives at
|
|
151
|
+
* api.builder.io/agent-native/gateway, while the internal origin is
|
|
152
|
+
* ai-services.builder.io).
|
|
152
153
|
* Override via BUILDER_GATEWAY_BASE_URL for staging / testing.
|
|
153
154
|
*/
|
|
154
155
|
export declare function getBuilderGatewayBaseUrl(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential-provider.d.ts","sourceRoot":"","sources":["../../src/server/credential-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B;IAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAK5C;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;gBAElB,IAAI,EAAE;QAChB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB;CAUF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvE;AAwBD,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyCxB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEvE;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGvE;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,OAAO,CAAC,CAEpE;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC;IACzD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC,CASD;AAUD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;IACL,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,EACD,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACxD,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAgCrD;AAED;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACxD,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBrD;AAeD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoDvE;AAOD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,IAAI,MAAM,CAO9C;AAED
|
|
1
|
+
{"version":3,"file":"credential-provider.d.ts","sourceRoot":"","sources":["../../src/server/credential-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -329,13 +329,14 @@ export function getBuilderProxyOrigin() {
|
|
|
329
329
|
}
|
|
330
330
|
/**
|
|
331
331
|
* Base URL for the public Builder LLM gateway (distinct from the internal
|
|
332
|
-
* proxy origin above — the public gateway lives at
|
|
333
|
-
* while the internal origin is
|
|
332
|
+
* proxy origin above — the public gateway lives at
|
|
333
|
+
* api.builder.io/agent-native/gateway, while the internal origin is
|
|
334
|
+
* ai-services.builder.io).
|
|
334
335
|
* Override via BUILDER_GATEWAY_BASE_URL for staging / testing.
|
|
335
336
|
*/
|
|
336
337
|
export function getBuilderGatewayBaseUrl() {
|
|
337
338
|
return (process.env.BUILDER_GATEWAY_BASE_URL ||
|
|
338
|
-
"https://api.builder.io/
|
|
339
|
+
"https://api.builder.io/agent-native/gateway/v1");
|
|
339
340
|
}
|
|
340
341
|
/** Authorization header value for Builder-proxied calls (env-only). */
|
|
341
342
|
export function getBuilderAuthHeader() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential-provider.js","sourceRoot":"","sources":["../../src/server/credential-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Credential provider abstraction.\n *\n * Every feature that needs an external credential (Anthropic API key,\n * Google OAuth tokens, OpenAI key, Slack bot token, etc.) should go through\n * one of the resolve*() helpers here instead of reading `process.env`\n * directly. That way the same feature can work in three modes:\n *\n * 1. User set their own key in .env → use it directly\n * 2. User connected Builder via `/cli-auth` → route through Builder proxy\n * 3. Neither → throw FeatureNotConfigured\n *\n * Templates catch FeatureNotConfigured and show a \"Connect Builder (1 click) /\n * set up your own key (guide)\" card.\n *\n * Today these helpers are used by the Builder-hosted LLM gateway, and the\n * shape is meant to grow to cover future managed credential integrations\n * (e.g. additional Builder-hosted services) without rewrites.\n */\n\nimport { getRequestUserEmail, getRequestOrgId } from \"./request-context.js\";\n\n/**\n * Decide which `app_secrets` scope a Builder/credential write should use.\n *\n * Org scope (\"everyone in this org sees these credentials\") wins when the\n * connecting user is an owner or admin of an active org — the write\n * privileges shared infra. A plain member or a user without an active\n * org falls through to per-user scope so a teammate can't silently\n * overwrite the org-shared connection.\n */\nexport function resolveCredentialWriteScope(\n email: string,\n orgId: string | null | undefined,\n role: string | null | undefined,\n): { scope: \"user\" | \"org\"; scopeId: string } {\n if (orgId && (role === \"owner\" || role === \"admin\")) {\n return { scope: \"org\", scopeId: orgId };\n }\n return { scope: \"user\", scopeId: email };\n}\n\nexport class FeatureNotConfiguredError extends Error {\n readonly requiredCredential: string;\n readonly builderConnectUrl?: string;\n readonly byokDocsUrl?: string;\n\n constructor(opts: {\n requiredCredential: string;\n message?: string;\n builderConnectUrl?: string;\n byokDocsUrl?: string;\n }) {\n super(\n opts.message ??\n `Feature requires credential \"${opts.requiredCredential}\". Connect Builder or set your own key.`,\n );\n this.name = \"FeatureNotConfiguredError\";\n this.requiredCredential = opts.requiredCredential;\n this.builderConnectUrl = opts.builderConnectUrl;\n this.byokDocsUrl = opts.byokDocsUrl;\n }\n}\n\n/**\n * Deployment-level credential fallback for single-tenant/local operation.\n * Multi-tenant call sites must gate this explicitly before calling.\n */\nexport function readDeployCredentialEnv(key: string): string | undefined {\n return process.env[key] || undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Builder credential resolution — two mutually-exclusive deployment modes:\n//\n// 1. **Single-tenant / env-managed.** When BUILDER_PRIVATE_KEY is set at\n// the deployment level, it is THE Builder identity for every user of\n// this deploy. The operator setting the env explicitly opts in to\n// \"everyone shares one Builder space\" — same shape as DATABASE_URL or\n// BETTER_AUTH_SECRET. The UI hides the per-user connect/disconnect\n// flow when env-managed (see `isBuilderEnvManaged`).\n//\n// 2. **Multi-tenant / per-user OAuth.** When the env is unset, each user\n// OAuth-connects their own Builder via the cli-auth flow. Their keys\n// land in `app_secrets` (scope=user, scopeId=email) via the callback\n// handler. They can disconnect via the settings panel.\n//\n// To run multi-tenant SaaS: leave the env unset. Setting BUILDER_PRIVATE_KEY\n// on a multi-tenant deploy will silently route every authenticated user\n// through the env-key owner's Builder identity — that was the KVesta Space\n// cross-tenant attribution leak (2026-04). The mode is binary: env-set\n// means single-tenant intent.\n// ---------------------------------------------------------------------------\n\nexport async function resolveBuilderCredential(\n key: string,\n): Promise<string | null> {\n // Env-managed mode wins when set: deploy-level Builder identity for\n // every user. Per-user app_secrets (left over from a previous OAuth\n // connection or a mode switch) are intentionally ignored — the\n // operator's deploy-level config is authoritative.\n const envValue = readDeployCredentialEnv(key);\n if (envValue) return envValue;\n\n const email = getRequestUserEmail();\n if (!email) return null;\n\n try {\n const { readAppSecret } = await import(\"../secrets/storage.js\");\n\n // 1. Per-user override: a user can paste their own key in settings to\n // overrule the org-shared one (handy for a personal sandbox).\n const userSecret = await readAppSecret({\n key,\n scope: \"user\",\n scopeId: email,\n });\n if (userSecret) return userSecret.value;\n\n // 2. Per-org shared credential: when one teammate connects Builder\n // as an owner/admin we write the OAuth result at org scope so\n // every member of that org gets the AI chat working without\n // re-running the connect flow. Resolution falls back here\n // silently — the caller never has to know which scope answered.\n const orgId = getRequestOrgId();\n if (orgId) {\n const orgSecret = await readAppSecret({\n key,\n scope: \"org\",\n scopeId: orgId,\n });\n if (orgSecret) return orgSecret.value;\n }\n } catch {\n // Secrets table not ready — treat as missing.\n }\n return null;\n}\n\n/**\n * True when `BUILDER_PRIVATE_KEY` is set at the deployment level — every\n * user of this deploy shares the operator's Builder identity, and per-user\n * connect/disconnect is disabled. UIs read this via `/builder/status` to\n * swap the \"Connect Builder\" prompts for a read-only \"managed by deployment\"\n * chip and to suppress the disconnect button.\n */\nexport function isBuilderEnvManaged(): boolean {\n return !!process.env.BUILDER_PRIVATE_KEY;\n}\n\n/**\n * Resolve the Builder private key for the current request. In env-managed\n * mode (deploy-level `BUILDER_PRIVATE_KEY` set) returns the env value for\n * every caller. Otherwise reads the current user's per-user OAuth-stored\n * key from `app_secrets`.\n */\nexport async function resolveBuilderPrivateKey(): Promise<string | null> {\n return resolveBuilderCredential(\"BUILDER_PRIVATE_KEY\");\n}\n\n/**\n * Resolve the current user's Builder auth header.\n * Returns `\"Bearer <key>\"` or null.\n */\nexport async function resolveBuilderAuthHeader(): Promise<string | null> {\n const key = await resolveBuilderPrivateKey();\n return key ? `Bearer ${key}` : null;\n}\n\n/**\n * Check whether the current user has a Builder private key configured\n * (per-user or deployment-level).\n */\nexport async function resolveHasBuilderPrivateKey(): Promise<boolean> {\n return !!(await resolveBuilderPrivateKey());\n}\n\n/**\n * Resolve all per-user Builder credentials. Used by the status endpoint\n * and agent-chat-plugin to get orgName, userId, etc.\n */\nexport async function resolveBuilderCredentials(): Promise<{\n privateKey: string | null;\n publicKey: string | null;\n userId: string | null;\n orgName: string | null;\n orgKind: string | null;\n}> {\n const [privateKey, publicKey, userId, orgName, orgKind] = await Promise.all([\n resolveBuilderCredential(\"BUILDER_PRIVATE_KEY\"),\n resolveBuilderCredential(\"BUILDER_PUBLIC_KEY\"),\n resolveBuilderCredential(\"BUILDER_USER_ID\"),\n resolveBuilderCredential(\"BUILDER_ORG_NAME\"),\n resolveBuilderCredential(\"BUILDER_ORG_KIND\"),\n ]);\n return { privateKey, publicKey, userId, orgName, orgKind };\n}\n\nconst BUILDER_CREDENTIAL_KEYS = [\n \"BUILDER_PRIVATE_KEY\",\n \"BUILDER_PUBLIC_KEY\",\n \"BUILDER_USER_ID\",\n \"BUILDER_ORG_NAME\",\n \"BUILDER_ORG_KIND\",\n] as const;\n\n/**\n * Write Builder credentials to `app_secrets`.\n *\n * Scope decision (see `resolveCredentialWriteScope`): when the connecting\n * user is owner/admin of an active org we write at `scope: \"org\"` so every\n * member of that org auto-resolves the credentials via\n * `resolveBuilderCredential`'s org fallback — no per-user re-connect\n * needed. A plain member or a user with no active org writes at\n * `scope: \"user\"` (the safe default that doesn't trample the org's shared\n * connection).\n *\n * Returns the actual scope/scopeId used so the caller can show \"Connected\n * for Builder.io\" vs \"Connected (personal)\" in the UI.\n */\nexport async function writeBuilderCredentials(\n email: string,\n creds: {\n privateKey: string;\n publicKey: string;\n userId?: string | null;\n orgName?: string | null;\n orgKind?: string | null;\n },\n options?: { orgId?: string | null; role?: string | null },\n): Promise<{ scope: \"user\" | \"org\"; scopeId: string }> {\n const { writeAppSecret } = await import(\"../secrets/storage.js\");\n const target = resolveCredentialWriteScope(\n email,\n options?.orgId ?? null,\n options?.role ?? null,\n );\n\n const entries: Array<{ key: string; value: string }> = [\n { key: \"BUILDER_PRIVATE_KEY\", value: creds.privateKey },\n { key: \"BUILDER_PUBLIC_KEY\", value: creds.publicKey },\n ];\n if (creds.userId) {\n entries.push({ key: \"BUILDER_USER_ID\", value: creds.userId });\n }\n if (creds.orgName) {\n entries.push({ key: \"BUILDER_ORG_NAME\", value: creds.orgName });\n }\n if (creds.orgKind) {\n entries.push({ key: \"BUILDER_ORG_KIND\", value: creds.orgKind });\n }\n await Promise.all(\n entries.map(({ key, value }) =>\n writeAppSecret({\n key,\n value,\n scope: target.scope,\n scopeId: target.scopeId,\n }),\n ),\n );\n return target;\n}\n\n/**\n * Delete Builder credentials.\n *\n * Default behaviour: clears only this user's per-user override (so a\n * member can disconnect their personal Builder identity without\n * collapsing the org-wide connection for every teammate). To revoke the\n * org's shared connection, pass `{ orgId, role }` for an owner/admin —\n * matching the same authority gate `writeBuilderCredentials` uses on\n * write. Plain members can never reach the org-scoped row.\n */\nexport async function deleteBuilderCredentials(\n email: string,\n options?: { orgId?: string | null; role?: string | null },\n): Promise<{ scope: \"user\" | \"org\"; scopeId: string }> {\n const { deleteAppSecret } = await import(\"../secrets/storage.js\");\n const target = resolveCredentialWriteScope(\n email,\n options?.orgId ?? null,\n options?.role ?? null,\n );\n await Promise.all(\n BUILDER_CREDENTIAL_KEYS.map((key) =>\n deleteAppSecret({\n key,\n scope: target.scope,\n scopeId: target.scopeId,\n }).catch(() => {}),\n ),\n );\n return target;\n}\n\n// ---------------------------------------------------------------------------\n// Generic request-scoped secret resolution\n//\n// New consumers should prefer this over reading `process.env.X` directly.\n// User-pasted and shared secrets live in `app_secrets` (encrypted). The\n// settings UI / onboarding panels can write user, org, or workspace rows.\n// Deploy-level env vars are the fallback for unauthenticated/CLI/background\n// contexts where there's no user to scope by — never the silent fallback\n// for an authenticated request, since on a multi-tenant deploy that would\n// silently identify every user as whoever set the deploy-level key\n// (KVesta Space, 2026-04).\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a request-scoped secret. Reads from `app_secrets` first (current\n * user override, active org, then workspace row); falls back to `process.env`\n * only for unauthenticated/CLI/background contexts.\n */\nexport async function resolveSecret(key: string): Promise<string | null> {\n const email = getRequestUserEmail();\n if (email) {\n try {\n const { readAppSecret } = await import(\"../secrets/storage.js\");\n // Per-user override first.\n const userSecret = await readAppSecret({\n key,\n scope: \"user\",\n scopeId: email,\n });\n if (userSecret?.value) return userSecret.value;\n\n const orgId = getRequestOrgId();\n if (orgId) {\n // Fall back to the active org's shared row, when present. Builder\n // Connect uses this first-class org scope.\n const orgSecret = await readAppSecret({\n key,\n scope: \"org\",\n scopeId: orgId,\n });\n if (orgSecret?.value) return orgSecret.value;\n\n // Registered secrets historically used \"workspace\" scope for\n // org-shared configuration. Keep reading it so Settings status and\n // runtime resolution agree.\n const workspaceSecret = await readAppSecret({\n key,\n scope: \"workspace\",\n scopeId: orgId,\n });\n if (workspaceSecret?.value) return workspaceSecret.value;\n } else {\n const soloWorkspaceSecret = await readAppSecret({\n key,\n scope: \"workspace\",\n scopeId: `solo:${email}`,\n });\n if (soloWorkspaceSecret?.value) return soloWorkspaceSecret.value;\n }\n } catch {\n // Secrets table not ready — treat as missing.\n }\n // Authenticated multi-tenant context: never fall back to process.env.\n // The deploy-level value would silently impersonate the actual key\n // owner across every tenant.\n return null;\n }\n // Unauthenticated / local-dev / CLI / background context: env fallback\n // is safe because there's no user to mis-identify.\n return process.env[key] || null;\n}\n\n// ---------------------------------------------------------------------------\n// Synchronous helpers — env-only fallbacks for contexts where per-user\n// lookup isn't possible (sync isConfigured checks, CLI scripts).\n// ---------------------------------------------------------------------------\n\n/**\n * True when a Builder private key is configured at the deployment level.\n *\n * This is the same check as `isBuilderEnvManaged()` (env-managed mode is\n * defined as \"deploy-level BUILDER_PRIVATE_KEY is set\"). Prefer\n * `isBuilderEnvManaged()` for new call sites — its name reflects what the\n * boolean means semantically. For \"does this user have access to Builder\n * (env or per-user)?\" use the async `resolveHasBuilderPrivateKey()`.\n */\nexport function hasBuilderPrivateKey(): boolean {\n return !!process.env.BUILDER_PRIVATE_KEY;\n}\n\n/** The origin for Builder-proxied API calls. Overridable for testing. */\nexport function getBuilderProxyOrigin(): string {\n return (\n process.env.BUILDER_PROXY_ORIGIN ||\n process.env.AIR_HOST ||\n process.env.BUILDER_API_HOST ||\n \"https://ai-services.builder.io\"\n );\n}\n\n/**\n * Base URL for the public Builder LLM gateway (distinct from the internal\n * proxy origin above — the public gateway lives at api.builder.io/codegen,\n * while the internal origin is ai-services.builder.io).\n * Override via BUILDER_GATEWAY_BASE_URL for staging / testing.\n */\nexport function getBuilderGatewayBaseUrl(): string {\n return (\n process.env.BUILDER_GATEWAY_BASE_URL ||\n \"https://api.builder.io/codegen/gateway/v1\"\n );\n}\n\n/** Authorization header value for Builder-proxied calls (env-only). */\nexport function getBuilderAuthHeader(): string | null {\n const key = process.env.BUILDER_PRIVATE_KEY;\n return key ? `Bearer ${key}` : null;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"credential-provider.js","sourceRoot":"","sources":["../../src/server/credential-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Credential provider abstraction.\n *\n * Every feature that needs an external credential (Anthropic API key,\n * Google OAuth tokens, OpenAI key, Slack bot token, etc.) should go through\n * one of the resolve*() helpers here instead of reading `process.env`\n * directly. That way the same feature can work in three modes:\n *\n * 1. User set their own key in .env → use it directly\n * 2. User connected Builder via `/cli-auth` → route through Builder proxy\n * 3. Neither → throw FeatureNotConfigured\n *\n * Templates catch FeatureNotConfigured and show a \"Connect Builder (1 click) /\n * set up your own key (guide)\" card.\n *\n * Today these helpers are used by the Builder-hosted LLM gateway, and the\n * shape is meant to grow to cover future managed credential integrations\n * (e.g. additional Builder-hosted services) without rewrites.\n */\n\nimport { getRequestUserEmail, getRequestOrgId } from \"./request-context.js\";\n\n/**\n * Decide which `app_secrets` scope a Builder/credential write should use.\n *\n * Org scope (\"everyone in this org sees these credentials\") wins when the\n * connecting user is an owner or admin of an active org — the write\n * privileges shared infra. A plain member or a user without an active\n * org falls through to per-user scope so a teammate can't silently\n * overwrite the org-shared connection.\n */\nexport function resolveCredentialWriteScope(\n email: string,\n orgId: string | null | undefined,\n role: string | null | undefined,\n): { scope: \"user\" | \"org\"; scopeId: string } {\n if (orgId && (role === \"owner\" || role === \"admin\")) {\n return { scope: \"org\", scopeId: orgId };\n }\n return { scope: \"user\", scopeId: email };\n}\n\nexport class FeatureNotConfiguredError extends Error {\n readonly requiredCredential: string;\n readonly builderConnectUrl?: string;\n readonly byokDocsUrl?: string;\n\n constructor(opts: {\n requiredCredential: string;\n message?: string;\n builderConnectUrl?: string;\n byokDocsUrl?: string;\n }) {\n super(\n opts.message ??\n `Feature requires credential \"${opts.requiredCredential}\". Connect Builder or set your own key.`,\n );\n this.name = \"FeatureNotConfiguredError\";\n this.requiredCredential = opts.requiredCredential;\n this.builderConnectUrl = opts.builderConnectUrl;\n this.byokDocsUrl = opts.byokDocsUrl;\n }\n}\n\n/**\n * Deployment-level credential fallback for single-tenant/local operation.\n * Multi-tenant call sites must gate this explicitly before calling.\n */\nexport function readDeployCredentialEnv(key: string): string | undefined {\n return process.env[key] || undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Builder credential resolution — two mutually-exclusive deployment modes:\n//\n// 1. **Single-tenant / env-managed.** When BUILDER_PRIVATE_KEY is set at\n// the deployment level, it is THE Builder identity for every user of\n// this deploy. The operator setting the env explicitly opts in to\n// \"everyone shares one Builder space\" — same shape as DATABASE_URL or\n// BETTER_AUTH_SECRET. The UI hides the per-user connect/disconnect\n// flow when env-managed (see `isBuilderEnvManaged`).\n//\n// 2. **Multi-tenant / per-user OAuth.** When the env is unset, each user\n// OAuth-connects their own Builder via the cli-auth flow. Their keys\n// land in `app_secrets` (scope=user, scopeId=email) via the callback\n// handler. They can disconnect via the settings panel.\n//\n// To run multi-tenant SaaS: leave the env unset. Setting BUILDER_PRIVATE_KEY\n// on a multi-tenant deploy will silently route every authenticated user\n// through the env-key owner's Builder identity — that was the KVesta Space\n// cross-tenant attribution leak (2026-04). The mode is binary: env-set\n// means single-tenant intent.\n// ---------------------------------------------------------------------------\n\nexport async function resolveBuilderCredential(\n key: string,\n): Promise<string | null> {\n // Env-managed mode wins when set: deploy-level Builder identity for\n // every user. Per-user app_secrets (left over from a previous OAuth\n // connection or a mode switch) are intentionally ignored — the\n // operator's deploy-level config is authoritative.\n const envValue = readDeployCredentialEnv(key);\n if (envValue) return envValue;\n\n const email = getRequestUserEmail();\n if (!email) return null;\n\n try {\n const { readAppSecret } = await import(\"../secrets/storage.js\");\n\n // 1. Per-user override: a user can paste their own key in settings to\n // overrule the org-shared one (handy for a personal sandbox).\n const userSecret = await readAppSecret({\n key,\n scope: \"user\",\n scopeId: email,\n });\n if (userSecret) return userSecret.value;\n\n // 2. Per-org shared credential: when one teammate connects Builder\n // as an owner/admin we write the OAuth result at org scope so\n // every member of that org gets the AI chat working without\n // re-running the connect flow. Resolution falls back here\n // silently — the caller never has to know which scope answered.\n const orgId = getRequestOrgId();\n if (orgId) {\n const orgSecret = await readAppSecret({\n key,\n scope: \"org\",\n scopeId: orgId,\n });\n if (orgSecret) return orgSecret.value;\n }\n } catch {\n // Secrets table not ready — treat as missing.\n }\n return null;\n}\n\n/**\n * True when `BUILDER_PRIVATE_KEY` is set at the deployment level — every\n * user of this deploy shares the operator's Builder identity, and per-user\n * connect/disconnect is disabled. UIs read this via `/builder/status` to\n * swap the \"Connect Builder\" prompts for a read-only \"managed by deployment\"\n * chip and to suppress the disconnect button.\n */\nexport function isBuilderEnvManaged(): boolean {\n return !!process.env.BUILDER_PRIVATE_KEY;\n}\n\n/**\n * Resolve the Builder private key for the current request. In env-managed\n * mode (deploy-level `BUILDER_PRIVATE_KEY` set) returns the env value for\n * every caller. Otherwise reads the current user's per-user OAuth-stored\n * key from `app_secrets`.\n */\nexport async function resolveBuilderPrivateKey(): Promise<string | null> {\n return resolveBuilderCredential(\"BUILDER_PRIVATE_KEY\");\n}\n\n/**\n * Resolve the current user's Builder auth header.\n * Returns `\"Bearer <key>\"` or null.\n */\nexport async function resolveBuilderAuthHeader(): Promise<string | null> {\n const key = await resolveBuilderPrivateKey();\n return key ? `Bearer ${key}` : null;\n}\n\n/**\n * Check whether the current user has a Builder private key configured\n * (per-user or deployment-level).\n */\nexport async function resolveHasBuilderPrivateKey(): Promise<boolean> {\n return !!(await resolveBuilderPrivateKey());\n}\n\n/**\n * Resolve all per-user Builder credentials. Used by the status endpoint\n * and agent-chat-plugin to get orgName, userId, etc.\n */\nexport async function resolveBuilderCredentials(): Promise<{\n privateKey: string | null;\n publicKey: string | null;\n userId: string | null;\n orgName: string | null;\n orgKind: string | null;\n}> {\n const [privateKey, publicKey, userId, orgName, orgKind] = await Promise.all([\n resolveBuilderCredential(\"BUILDER_PRIVATE_KEY\"),\n resolveBuilderCredential(\"BUILDER_PUBLIC_KEY\"),\n resolveBuilderCredential(\"BUILDER_USER_ID\"),\n resolveBuilderCredential(\"BUILDER_ORG_NAME\"),\n resolveBuilderCredential(\"BUILDER_ORG_KIND\"),\n ]);\n return { privateKey, publicKey, userId, orgName, orgKind };\n}\n\nconst BUILDER_CREDENTIAL_KEYS = [\n \"BUILDER_PRIVATE_KEY\",\n \"BUILDER_PUBLIC_KEY\",\n \"BUILDER_USER_ID\",\n \"BUILDER_ORG_NAME\",\n \"BUILDER_ORG_KIND\",\n] as const;\n\n/**\n * Write Builder credentials to `app_secrets`.\n *\n * Scope decision (see `resolveCredentialWriteScope`): when the connecting\n * user is owner/admin of an active org we write at `scope: \"org\"` so every\n * member of that org auto-resolves the credentials via\n * `resolveBuilderCredential`'s org fallback — no per-user re-connect\n * needed. A plain member or a user with no active org writes at\n * `scope: \"user\"` (the safe default that doesn't trample the org's shared\n * connection).\n *\n * Returns the actual scope/scopeId used so the caller can show \"Connected\n * for Builder.io\" vs \"Connected (personal)\" in the UI.\n */\nexport async function writeBuilderCredentials(\n email: string,\n creds: {\n privateKey: string;\n publicKey: string;\n userId?: string | null;\n orgName?: string | null;\n orgKind?: string | null;\n },\n options?: { orgId?: string | null; role?: string | null },\n): Promise<{ scope: \"user\" | \"org\"; scopeId: string }> {\n const { writeAppSecret } = await import(\"../secrets/storage.js\");\n const target = resolveCredentialWriteScope(\n email,\n options?.orgId ?? null,\n options?.role ?? null,\n );\n\n const entries: Array<{ key: string; value: string }> = [\n { key: \"BUILDER_PRIVATE_KEY\", value: creds.privateKey },\n { key: \"BUILDER_PUBLIC_KEY\", value: creds.publicKey },\n ];\n if (creds.userId) {\n entries.push({ key: \"BUILDER_USER_ID\", value: creds.userId });\n }\n if (creds.orgName) {\n entries.push({ key: \"BUILDER_ORG_NAME\", value: creds.orgName });\n }\n if (creds.orgKind) {\n entries.push({ key: \"BUILDER_ORG_KIND\", value: creds.orgKind });\n }\n await Promise.all(\n entries.map(({ key, value }) =>\n writeAppSecret({\n key,\n value,\n scope: target.scope,\n scopeId: target.scopeId,\n }),\n ),\n );\n return target;\n}\n\n/**\n * Delete Builder credentials.\n *\n * Default behaviour: clears only this user's per-user override (so a\n * member can disconnect their personal Builder identity without\n * collapsing the org-wide connection for every teammate). To revoke the\n * org's shared connection, pass `{ orgId, role }` for an owner/admin —\n * matching the same authority gate `writeBuilderCredentials` uses on\n * write. Plain members can never reach the org-scoped row.\n */\nexport async function deleteBuilderCredentials(\n email: string,\n options?: { orgId?: string | null; role?: string | null },\n): Promise<{ scope: \"user\" | \"org\"; scopeId: string }> {\n const { deleteAppSecret } = await import(\"../secrets/storage.js\");\n const target = resolveCredentialWriteScope(\n email,\n options?.orgId ?? null,\n options?.role ?? null,\n );\n await Promise.all(\n BUILDER_CREDENTIAL_KEYS.map((key) =>\n deleteAppSecret({\n key,\n scope: target.scope,\n scopeId: target.scopeId,\n }).catch(() => {}),\n ),\n );\n return target;\n}\n\n// ---------------------------------------------------------------------------\n// Generic request-scoped secret resolution\n//\n// New consumers should prefer this over reading `process.env.X` directly.\n// User-pasted and shared secrets live in `app_secrets` (encrypted). The\n// settings UI / onboarding panels can write user, org, or workspace rows.\n// Deploy-level env vars are the fallback for unauthenticated/CLI/background\n// contexts where there's no user to scope by — never the silent fallback\n// for an authenticated request, since on a multi-tenant deploy that would\n// silently identify every user as whoever set the deploy-level key\n// (KVesta Space, 2026-04).\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a request-scoped secret. Reads from `app_secrets` first (current\n * user override, active org, then workspace row); falls back to `process.env`\n * only for unauthenticated/CLI/background contexts.\n */\nexport async function resolveSecret(key: string): Promise<string | null> {\n const email = getRequestUserEmail();\n if (email) {\n try {\n const { readAppSecret } = await import(\"../secrets/storage.js\");\n // Per-user override first.\n const userSecret = await readAppSecret({\n key,\n scope: \"user\",\n scopeId: email,\n });\n if (userSecret?.value) return userSecret.value;\n\n const orgId = getRequestOrgId();\n if (orgId) {\n // Fall back to the active org's shared row, when present. Builder\n // Connect uses this first-class org scope.\n const orgSecret = await readAppSecret({\n key,\n scope: \"org\",\n scopeId: orgId,\n });\n if (orgSecret?.value) return orgSecret.value;\n\n // Registered secrets historically used \"workspace\" scope for\n // org-shared configuration. Keep reading it so Settings status and\n // runtime resolution agree.\n const workspaceSecret = await readAppSecret({\n key,\n scope: \"workspace\",\n scopeId: orgId,\n });\n if (workspaceSecret?.value) return workspaceSecret.value;\n } else {\n const soloWorkspaceSecret = await readAppSecret({\n key,\n scope: \"workspace\",\n scopeId: `solo:${email}`,\n });\n if (soloWorkspaceSecret?.value) return soloWorkspaceSecret.value;\n }\n } catch {\n // Secrets table not ready — treat as missing.\n }\n // Authenticated multi-tenant context: never fall back to process.env.\n // The deploy-level value would silently impersonate the actual key\n // owner across every tenant.\n return null;\n }\n // Unauthenticated / local-dev / CLI / background context: env fallback\n // is safe because there's no user to mis-identify.\n return process.env[key] || null;\n}\n\n// ---------------------------------------------------------------------------\n// Synchronous helpers — env-only fallbacks for contexts where per-user\n// lookup isn't possible (sync isConfigured checks, CLI scripts).\n// ---------------------------------------------------------------------------\n\n/**\n * True when a Builder private key is configured at the deployment level.\n *\n * This is the same check as `isBuilderEnvManaged()` (env-managed mode is\n * defined as \"deploy-level BUILDER_PRIVATE_KEY is set\"). Prefer\n * `isBuilderEnvManaged()` for new call sites — its name reflects what the\n * boolean means semantically. For \"does this user have access to Builder\n * (env or per-user)?\" use the async `resolveHasBuilderPrivateKey()`.\n */\nexport function hasBuilderPrivateKey(): boolean {\n return !!process.env.BUILDER_PRIVATE_KEY;\n}\n\n/** The origin for Builder-proxied API calls. Overridable for testing. */\nexport function getBuilderProxyOrigin(): string {\n return (\n process.env.BUILDER_PROXY_ORIGIN ||\n process.env.AIR_HOST ||\n process.env.BUILDER_API_HOST ||\n \"https://ai-services.builder.io\"\n );\n}\n\n/**\n * Base URL for the public Builder LLM gateway (distinct from the internal\n * proxy origin above — the public gateway lives at\n * api.builder.io/agent-native/gateway, while the internal origin is\n * ai-services.builder.io).\n * Override via BUILDER_GATEWAY_BASE_URL for staging / testing.\n */\nexport function getBuilderGatewayBaseUrl(): string {\n return (\n process.env.BUILDER_GATEWAY_BASE_URL ||\n \"https://api.builder.io/agent-native/gateway/v1\"\n );\n}\n\n/** Authorization header value for Builder-proxied calls (env-only). */\nexport function getBuilderAuthHeader(): string | null {\n const key = process.env.BUILDER_PRIVATE_KEY;\n return key ? `Bearer ${key}` : null;\n}\n"]}
|
|
@@ -30,6 +30,32 @@ The `create` command defaults to a workspace monorepo. It shows a multi-select p
|
|
|
30
30
|
|
|
31
31
|
Open the URL the dev server prints. Workspace apps use app-specific ports, often `http://localhost:8080` or another 808x port; standalone apps usually use `http://localhost:3000`.
|
|
32
32
|
|
|
33
|
+
## Creating vs adding apps {#creating-vs-adding-apps}
|
|
34
|
+
|
|
35
|
+
Run `create` from the folder where you want a brand-new workspace:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
cd ~/projects
|
|
39
|
+
npx @agent-native/core create my-platform
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
After a workspace exists, run app commands from the workspace root:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cd my-platform
|
|
46
|
+
npx @agent-native/core add-app
|
|
47
|
+
pnpm install
|
|
48
|
+
pnpm dev
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
If your terminal is inside `apps/content` or another app folder, the CLI still detects the workspace and adds the new app as a sibling under `apps/`. Afterward, go back to the workspace root before running `pnpm install` or `pnpm dev`.
|
|
52
|
+
|
|
53
|
+
To make a second app from the same template, give it a new app name:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx @agent-native/core add-app design-lab --template design
|
|
57
|
+
```
|
|
58
|
+
|
|
33
59
|
## What just happened? {#what-just-happened}
|
|
34
60
|
|
|
35
61
|
You now have a real, full-featured app running on your machine. Open it in the browser and try it:
|
|
@@ -71,6 +71,23 @@ pnpm dlx @agent-native/core create my-platform
|
|
|
71
71
|
|
|
72
72
|
Dispatch is usually scaffolded into a workspace alongside the apps it coordinates. For a workspace, Dispatch's shared auth, database, and brand are inherited from the workspace core — see [Multi-App Workspace](/docs/multi-app-workspace).
|
|
73
73
|
|
|
74
|
+
## First local run {#first-local-run}
|
|
75
|
+
|
|
76
|
+
From the workspace root:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pnpm install
|
|
80
|
+
pnpm dev
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Open the Dispatch URL printed by the dev server. Local development uses the same Better Auth sign-in flow as production. Create a local account with email + password; email verification is skipped in development, and the password is stored only in your local app database. There is no supported auth bypass in the default scaffold, because the agent, workspace resources, vault, and sharing model all rely on a real user session.
|
|
84
|
+
|
|
85
|
+
You can click through the Dispatch UI after signing in. To use the chat composer or run agent tasks, connect an LLM provider first:
|
|
86
|
+
|
|
87
|
+
1. Open **Settings**.
|
|
88
|
+
2. In **LLM**, either connect Builder.io or add your own provider key such as `ANTHROPIC_API_KEY`.
|
|
89
|
+
3. Return to **Overview** and try the composer.
|
|
90
|
+
|
|
74
91
|
## Customize it {#customize}
|
|
75
92
|
|
|
76
93
|
Dispatch is a full template like any other — see [Templates](/docs/cloneable-saas). Ask the agent to "add a new integration for Datadog" or "route Slack DMs from channel X to the issues agent" and it'll edit the routing config, add the webhook handler, and wire it up.
|