@opengeni/core 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sandbox/fleet.ts","../src/sandbox/routing.ts","../src/access/index.ts","../src/billing/limits.ts","../src/domain/capabilities.ts","../src/domain/environments.ts","../src/domain/packs.ts","../src/domain/resources.ts","../src/domain/scheduled-tasks.ts","../src/domain/sessions.ts","../src/domain/workspace-members.ts"],"sourcesContent":["// apps/api/src/sandbox/fleet.ts — the FLEET service backing the fleet MCP tools\n// (M7): list / attach / swap / run_on / provision over the heterogeneous fleet\n// (the session's Modal group box + the workspace's enrolled selfhosted machines).\n//\n// Each operation is workspace-scoped (the caller's grant) and, for the\n// session-pointer mutations (attach/swap), session-scoped (the worker-signed\n// sessionId claim). The swap is the epoch-fenced CAS `setActiveSandbox`: it bumps\n// active_epoch + repoints active_sandbox_id, which the routing proxy reads on the\n// NEXT tool call. Liveness for a selfhosted target is a real ControlRpc ping over\n// the events bus (the subject IS the registry); a Modal box is \"live\" while its\n// session group exists. `run_on` builds a one-off backend session and runs a\n// single op WITHOUT touching the active pointer.\n\nimport type { Settings } from \"@opengeni/config\";\nimport {\n getEnrollment,\n getSandbox,\n listEnrollments,\n listSandboxes,\n readActiveSandbox,\n requireSession,\n setActiveSandbox,\n type Database,\n type EnrollmentRecord,\n type SandboxRecord,\n} from \"@opengeni/db\";\nimport type { EventBus } from \"@opengeni/events\";\nimport {\n NatsControlRpc,\n selfhostedLiveness,\n SelfhostedSession,\n type ControlRpc,\n type NatsRequestConnection,\n} from \"@opengeni/runtime/sandbox\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { relayConfigFromSettings } from \"./routing\";\n\nexport type FleetServices = {\n db: Database;\n settings: Settings;\n bus?: EventBus;\n};\n\nexport type FleetContext = {\n accountId: string;\n workspaceId: string;\n /** The calling session (the pointer the attach/swap mutates + whose group box\n * is the default fleet member). */\n sessionId: string;\n /** The session's own group sandbox backend (modal/selfhosted/…). */\n sessionBackend: string;\n /** The session's own group sandbox id (the lease group). */\n sessionGroupId: string;\n};\n\n/**\n * Build a session-scoped {@link FleetContext}: load the session (workspace-\n * scoped), reject a session with no box (backend:none — the fleet is only\n * meaningful for a sandboxed session), and project its group backend/id. Shared\n * by the worker-signed MCP fleet tools and the user-authenticated swap REST\n * route so both resolve the SAME context (no drift). The `accountId`/`workspaceId`/\n * `sessionId` come from the trusted grant/route; the backend + group id come from\n * the session row.\n */\nexport async function buildFleetContextForSession(\n deps: { db: Database },\n ctx: { accountId: string; workspaceId: string; sessionId: string },\n): Promise<FleetContext> {\n const session = await requireSession(deps.db, ctx.workspaceId, ctx.sessionId);\n if (session.sandboxBackend === \"none\") {\n throw new HTTPException(422, {\n message: \"this session has no sandbox (backend: none); the fleet is unavailable\",\n });\n }\n return {\n accountId: ctx.accountId,\n workspaceId: ctx.workspaceId,\n sessionId: ctx.sessionId,\n sessionBackend: session.sandboxBackend,\n sessionGroupId: session.sandboxGroupId,\n };\n}\n\n/** The dominant liveness of a fleet member, surfaced to the dock + the agent. */\nexport type FleetLiveness = \"online\" | \"reconnecting\" | \"offline\";\n\n/**\n * A fleet member as the agent + the dock see it (the M8b/M9 UI seam — the\n * `sandboxes_list` response entry the dock renders). STABLE shape: the dock keys\n * on `id`, renders `name`/`kind`/`liveness`, and marks `active`. The session's own\n * Modal group box is a synthetic entry with `id: groupId`, `kind: \"modal\"`, and a\n * null `enrollmentId`; an enrolled machine carries its sandbox + enrollment ids.\n */\nexport type FleetSandboxEntry = {\n /** The sandbox id used as the attach/swap/run_on `target`. For the session's\n * own group box this is the group id (a null active pointer == this box). */\n id: string;\n kind: \"modal\" | \"selfhosted\";\n name: string;\n liveness: FleetLiveness;\n /** True for the session's currently-active sandbox (the routing target). */\n active: boolean;\n /** True for the session's own group box (the default/home sandbox). */\n isSessionGroup: boolean;\n enrollmentId: string | null;\n /** Whether this target can be attached/swapped to right now (live + addressable). */\n attachable: boolean;\n /** Selfhosted only: whether whole-machine + screen-control consent is acked. */\n consented?: boolean;\n /** Selfhosted only: whether a display (real/Xvfb) is present. */\n hasDisplay?: boolean;\n lastSeenAt?: string | null;\n};\n\nexport type FleetListResult = {\n /** The session's currently-active sandbox id, or null == the group box. */\n activeSandboxId: string | null;\n activeEpoch: number;\n sandboxes: FleetSandboxEntry[];\n};\n\n/** A swap/attach outcome the tool returns. */\nexport type FleetSwapResult = {\n swapped: boolean;\n activeSandboxId: string | null;\n activeEpoch: number;\n reason?: string;\n};\n\nconst PROBE_TIMEOUT_MS = 5_000;\n\nfunction controlRpc(bus: EventBus | undefined): ControlRpc {\n return new NatsControlRpc(async (): Promise<NatsRequestConnection | null> => {\n if (!bus) {\n return null;\n }\n return bus.getRequestConnection();\n });\n}\n\n/** Probe an enrolled machine's liveness: a real ControlRpc ping (the subject IS\n * the registry), mapped through `selfhostedLiveness` (the enrollment row's\n * status/consent/display + lastSeenAt disambiguate a probe-miss into\n * reconnecting vs offline). A revoked/never-seen enrollment is offline without a\n * probe. */\nasync function probeEnrollment(\n services: FleetServices,\n workspaceId: string,\n enrollment: EnrollmentRecord,\n): Promise<{ liveness: FleetLiveness; consented: boolean; hasDisplay: boolean }> {\n const { settings, bus } = services;\n let probeResponded = false;\n if (enrollment.status === \"active\") {\n const session = new SelfhostedSession({\n workspaceId,\n agentId: enrollment.id,\n controlRpc: controlRpc(bus),\n relay: relayConfigFromSettings(settings),\n timeoutMs: PROBE_TIMEOUT_MS,\n });\n try {\n probeResponded = await session.ping();\n } catch {\n probeResponded = false;\n }\n }\n const state = selfhostedLiveness({\n enrollment: {\n status: enrollment.status,\n exposure: enrollment.exposure,\n allowScreenControl: enrollment.allowScreenControl,\n hasDisplay: enrollment.hasDisplay,\n lastSeenAt: enrollment.lastSeenAt,\n },\n probeResponded,\n });\n return { liveness: state.state, consented: state.consented, hasDisplay: state.hasDisplay };\n}\n\n/**\n * List the fleet: the session's own Modal group box (a synthetic entry) + the\n * workspace's first-class selfhosted sandboxes (each probed for liveness), each\n * with an `active` marker derived from the session's active pointer.\n */\nexport async function listFleet(services: FleetServices, ctx: FleetContext): Promise<FleetListResult> {\n const { db } = services;\n const pointer = (await readActiveSandbox(db, ctx.workspaceId, ctx.sessionId)) ?? {\n activeSandboxId: null,\n activeEpoch: 0,\n };\n\n const entries: FleetSandboxEntry[] = [];\n\n // The session's own group box (the default/home sandbox; null active pointer ==\n // this box). It is live by virtue of being the session's resumable group.\n const groupActive = pointer.activeSandboxId === null;\n entries.push({\n id: ctx.sessionGroupId,\n kind: ctx.sessionBackend === \"selfhosted\" ? \"selfhosted\" : \"modal\",\n name: \"session sandbox\",\n liveness: \"online\",\n active: groupActive,\n isSessionGroup: true,\n enrollmentId: null,\n attachable: true,\n });\n\n // The workspace's first-class selfhosted sandboxes (enrolled machines). Probe\n // each for liveness; a missing enrollment is offline.\n const sandboxes = await listSandboxes(db, ctx.workspaceId);\n for (const sandbox of sandboxes) {\n if (sandbox.kind !== \"selfhosted\" || !sandbox.enrollmentId) {\n continue;\n }\n const enrollment = await getEnrollment(db, ctx.workspaceId, sandbox.enrollmentId);\n const probe = enrollment\n ? await probeEnrollment(services, ctx.workspaceId, enrollment)\n : { liveness: \"offline\" as FleetLiveness, consented: false, hasDisplay: false };\n entries.push({\n id: sandbox.id,\n kind: \"selfhosted\",\n name: sandbox.name,\n liveness: probe.liveness,\n active: pointer.activeSandboxId === sandbox.id,\n isSessionGroup: false,\n enrollmentId: sandbox.enrollmentId,\n attachable: probe.liveness === \"online\",\n consented: probe.consented,\n hasDisplay: probe.hasDisplay,\n lastSeenAt: enrollment?.lastSeenAt ?? null,\n });\n }\n\n return { activeSandboxId: pointer.activeSandboxId, activeEpoch: pointer.activeEpoch, sandboxes: entries };\n}\n\n/** Resolve a swap target id → the value `setActiveSandbox` writes. The session's\n * own group id maps to NULL (the default pointer); a first-class sandbox id is\n * validated (workspace ownership + liveness) and written verbatim. */\nasync function resolveTarget(\n services: FleetServices,\n ctx: FleetContext,\n target: string,\n): Promise<{ ok: true; targetSandboxId: string | null } | { ok: false; reason: string }> {\n // The session's own group box → the default pointer (null).\n if (target === ctx.sessionGroupId || target === \"session\" || target === \"default\") {\n return { ok: true, targetSandboxId: null };\n }\n const sandbox = await getSandbox(services.db, ctx.workspaceId, target);\n if (!sandbox) {\n return { ok: false, reason: `sandbox ${target} not found in this workspace` };\n }\n if (sandbox.kind === \"selfhosted\") {\n if (!sandbox.enrollmentId) {\n return { ok: false, reason: `selfhosted sandbox ${target} has no enrollment` };\n }\n const enrollment = await getEnrollment(services.db, ctx.workspaceId, sandbox.enrollmentId);\n if (!enrollment) {\n return { ok: false, reason: `enrollment for sandbox ${target} not found` };\n }\n const probe = await probeEnrollment(services, ctx.workspaceId, enrollment);\n if (probe.liveness !== \"online\") {\n return { ok: false, reason: `sandbox ${target} is ${probe.liveness}; cannot attach to a non-online machine` };\n }\n }\n return { ok: true, targetSandboxId: sandbox.id };\n}\n\n/**\n * THE SWAP (and attach — identical mechanic). Validate the target's ownership +\n * liveness, then repoint the session via the epoch-fenced CAS `setActiveSandbox`:\n * read the current epoch, then CAS on it. A concurrent double-swap lets exactly\n * one win; the loser re-reads + may retry. The bumped epoch fences any in-flight\n * op cached against the old pointer, which then retries against the new active\n * sandbox (the routing proxy's fenced-retry role).\n */\nexport async function swapActiveSandbox(\n services: FleetServices,\n ctx: FleetContext,\n target: string,\n // The session's working directory to seed alongside the pointer (create-time\n // machine targeting). OMITTED ⇒ the column is left unchanged (a live swap/attach\n // never touches it); threaded straight into the epoch-fenced setActiveSandbox CAS.\n workingDir?: string | null,\n): Promise<FleetSwapResult> {\n const resolved = await resolveTarget(services, ctx, target);\n if (!resolved.ok) {\n const pointer = (await readActiveSandbox(services.db, ctx.workspaceId, ctx.sessionId)) ?? {\n activeSandboxId: null,\n activeEpoch: 0,\n };\n return { swapped: false, activeSandboxId: pointer.activeSandboxId, activeEpoch: pointer.activeEpoch, reason: resolved.reason };\n }\n\n // Read the current epoch, then CAS on it (the fence). One retry on a lost race\n // (a concurrent swap bumped the epoch between read and write).\n for (let attempt = 0; attempt < 2; attempt += 1) {\n const pointer = (await readActiveSandbox(services.db, ctx.workspaceId, ctx.sessionId)) ?? {\n activeSandboxId: null,\n activeEpoch: 0,\n };\n // No-op swap (already pointed there) is a success without an epoch bump churn.\n if (pointer.activeSandboxId === resolved.targetSandboxId) {\n return { swapped: true, activeSandboxId: pointer.activeSandboxId, activeEpoch: pointer.activeEpoch };\n }\n const result = await setActiveSandbox(services.db, {\n accountId: ctx.accountId,\n workspaceId: ctx.workspaceId,\n sessionId: ctx.sessionId,\n targetSandboxId: resolved.targetSandboxId,\n expectedEpoch: pointer.activeEpoch,\n ...(workingDir !== undefined ? { workingDir } : {}),\n });\n if (result.swapped && result.pointer) {\n return { swapped: true, activeSandboxId: result.pointer.activeSandboxId, activeEpoch: result.pointer.activeEpoch };\n }\n // CAS lost (a concurrent swap won) — re-read + retry once.\n }\n const pointer = (await readActiveSandbox(services.db, ctx.workspaceId, ctx.sessionId)) ?? {\n activeSandboxId: null,\n activeEpoch: 0,\n };\n return {\n swapped: false,\n activeSandboxId: pointer.activeSandboxId,\n activeEpoch: pointer.activeEpoch,\n reason: \"a concurrent swap won the epoch fence; re-read and retry\",\n };\n}\n\nexport type RunOnOp =\n | { kind: \"exec\"; cmd: string; workdir?: string }\n | { kind: \"read\"; path: string }\n | { kind: \"write\"; path: string; content: string };\n\nexport type RunOnResult = {\n target: string;\n kind: string;\n ok: boolean;\n stdout?: string;\n stderr?: string;\n exitCode?: number | null;\n content?: string;\n bytesWritten?: number;\n reason?: string;\n};\n\n/**\n * Run a ONE-OFF op against a SPECIFIC target WITHOUT changing the active pointer\n * (the dossier `run_on`). Only selfhosted targets are routable as a one-off here\n * (a Modal target is the session's group box, reached via the normal Channel-A /\n * turn path — `run_on` is for reaching a NON-active enrolled machine without\n * swapping). The op is fenced under the target's enrollment, addressed to its\n * agent subject; an offline machine surfaces a clear reason, never a wrong-box\n * landing.\n */\nexport async function runOnSandbox(\n services: FleetServices,\n ctx: FleetContext,\n target: string,\n op: RunOnOp,\n): Promise<RunOnResult> {\n const sandbox = await getSandbox(services.db, ctx.workspaceId, target);\n if (!sandbox) {\n return { target, kind: op.kind, ok: false, reason: `sandbox ${target} not found in this workspace` };\n }\n if (sandbox.kind !== \"selfhosted\" || !sandbox.enrollmentId) {\n return {\n target,\n kind: op.kind,\n ok: false,\n reason: `run_on routes one-off ops to enrolled selfhosted machines; ${sandbox.kind} targets are reached via the active sandbox (swap to it first)`,\n };\n }\n const enrollment = await getEnrollment(services.db, ctx.workspaceId, sandbox.enrollmentId);\n if (!enrollment || enrollment.status !== \"active\") {\n return { target, kind: op.kind, ok: false, reason: `sandbox ${target} is not enrolled/active` };\n }\n\n const session = new SelfhostedSession({\n workspaceId: ctx.workspaceId,\n agentId: sandbox.enrollmentId,\n controlRpc: controlRpc(services.bus),\n relay: relayConfigFromSettings(services.settings),\n });\n\n try {\n if (op.kind === \"exec\") {\n const res = await session.exec({ cmd: op.cmd, ...(op.workdir ? { workdir: op.workdir } : {}) });\n return { target, kind: \"exec\", ok: true, stdout: res.stdout, stderr: res.stderr, exitCode: res.exitCode };\n }\n if (op.kind === \"read\") {\n const bytes = await session.readFile({ path: op.path });\n return { target, kind: \"read\", ok: true, content: new TextDecoder().decode(bytes) };\n }\n // write\n const bytesWritten = await session.writeFile({ path: op.path, content: op.content });\n return { target, kind: \"write\", ok: true, bytesWritten };\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return { target, kind: op.kind, ok: false, reason };\n }\n}\n\nexport type ProvisionResult =\n | {\n kind: \"selfhosted\";\n instructions: string;\n installCommandUnix: string;\n installCommandWindows: string;\n verificationUri: string;\n note: string;\n }\n | { kind: \"modal\"; sandbox: SandboxRecord; note: string };\n\n/**\n * Provision a new fleet member.\n * - selfhosted → return the device-flow enrollment instructions (the agent\n * surfaces them to a HUMAN, who installs the agent + enrolls — the agent\n * cannot click the loud whole-machine consent itself).\n * - modal → create a first-class named modal `sandboxes` record (a swap target).\n * NOTE: the Modal BOX is materialized lazily when first swapped-to (Modal\n * lifecycle is owned by the lease — unchanged per dossier §21).\n */\nexport async function provisionSandbox(\n services: FleetServices,\n ctx: FleetContext,\n input: { kind: \"selfhosted\" | \"modal\"; name?: string },\n): Promise<ProvisionResult> {\n if (input.kind === \"selfhosted\") {\n const base = (services.settings.publicBaseUrl ?? \"https://get.opengeni.ai\").replace(/\\/+$/, \"\");\n return {\n kind: \"selfhosted\",\n instructions:\n \"Share these instructions with a human operator. They install the OpenGeni agent on the machine, run `opengeni-agent enroll`, complete the device-flow at the verification URL (the loud whole-machine + screen-control consent), and the machine then appears here as an attachable selfhosted sandbox.\",\n // Install from THIS control plane's origin (not a hardcoded public CDN): the\n // served install script is rewritten to pull the per-SHA agent baked into\n // this exact deployment (see apps/api/src/routes/install.ts), so a deployed\n // env is self-contained and a private/air-gapped one works with no public DNS.\n installCommandUnix: `curl -fsSL ${base}/install.sh | sh`,\n installCommandWindows: `irm ${base}/install.ps1 | iex`,\n verificationUri: `${base}/device`,\n note: \"Whole-machine access requires explicit human consent in the device-flow web page; the agent cannot self-consent.\",\n };\n }\n // modal: create a first-class named modal sandbox record (a swap target). The\n // box is materialized lazily on first swap (Modal lifecycle unchanged).\n const { createSandbox } = await import(\"@opengeni/db\");\n const sandbox = await createSandbox(services.db, {\n accountId: ctx.accountId,\n workspaceId: ctx.workspaceId,\n kind: \"modal\",\n name: input.name?.trim() || \"modal-box\",\n });\n return {\n kind: \"modal\",\n sandbox,\n note: \"A named Modal sandbox record was created. Its box is materialized when first swapped-to; the session's own group box remains the default until then.\",\n };\n}\n","// apps/api/src/sandbox/routing.ts — wire the agent-loop-free routing proxy to the\n// real DB pointer + the live NATS control plane for the API-DIRECT Channel-A path\n// (M7). Symmetric with apps/worker/src/sandbox-routing.ts (the turn path).\n//\n// A Channel-A op resumes the group box by id and runs ONE op against it. With\n// hot-swap, the op must land on the session's CURRENTLY-active sandbox, not\n// always the group box: if the session swapped to a selfhosted machine, an\n// fs.read / git.status / exec from the API must reach THAT machine. So the\n// established group session is wrapped in a `RoutingSandboxSession` that re-reads\n// (active_sandbox_id, active_epoch) and dispatches to the active backend.\n//\n// The DB-coupled glue (readActiveSandbox / getSandbox / the selfhosted ControlRpc\n// over the events bus) lives here, not in the leaf (which stays db-free).\n\nimport type { Settings } from \"@opengeni/config\";\nimport { getSandbox, readActiveSandbox, type Database } from \"@opengeni/db\";\nimport type { EventBus } from \"@opengeni/events\";\nimport {\n makeActiveBackendResolver,\n NatsControlRpc,\n RoutingSandboxSession,\n type ControlRpc,\n type EstablishedSandboxSession,\n type NatsRequestConnection,\n type RoutableBackendSession,\n type RoutableSandbox,\n type SelfhostedRelayConfig,\n} from \"@opengeni/runtime/sandbox\";\n\nexport type ChannelARoutingServices = {\n db: Database;\n settings: Settings;\n bus?: EventBus;\n};\n\n/** Map the deployment relay URL to the leaf's `SelfhostedRelayConfig` shape. The\n * relay URL (`OPENGENI_SELFHOSTED_RELAY_URL`) may carry a path (the relay's wss\n * route); a path-less URL defaults to the relay's `/stream` route (M8b). */\nexport function relayConfigFromSettings(settings: Settings): SelfhostedRelayConfig {\n const raw = settings.selfhostedRelayUrl?.trim();\n if (!raw) {\n return { host: \"relay.opengeni.local\", port: 443, tls: true, path: \"/stream\" };\n }\n try {\n const url = new URL(raw.includes(\"://\") ? raw : `wss://${raw}`);\n const tls = url.protocol === \"wss:\" || url.protocol === \"https:\";\n const port = url.port ? Number(url.port) : tls ? 443 : 80;\n // Honor an explicit path in the configured URL; default the relay's /stream.\n const path = url.pathname && url.pathname !== \"/\" ? url.pathname : \"/stream\";\n return { host: url.hostname, port, tls, path };\n } catch {\n return { host: raw, port: 443, tls: true, path: \"/stream\" };\n }\n}\n\n/** The canonical relay dial-BASE URL (`scheme://host[:port]/stream`) handed to the\n * agent PRODUCER. The agent's relay channel appends ONLY its routing query to\n * this base (`channel.rs`: `format!(\"{relay_url}{sep}{query}\")`) and relies on the\n * base ALREADY carrying the relay's `/stream` route. `OPENGENI_SELFHOSTED_RELAY_URL`\n * is frequently pathless (e.g. `wss://relay.<env>.app.opengeni.ai`), which made the\n * producer dial a path-less URL the relay 400s. Derive the base from the SAME parser\n * the CONSUMER uses (`relayConfigFromSettings`) so producer + consumer always agree\n * on `/stream` — even when the configured URL omits it. An unconfigured relay maps to\n * `\"\"` (graceful degrade: the agent reports no-relay rather than dialing a synthetic\n * host). Fixes preview AND managed prod with no agent rebuild (dossier §V5/§V6). */\nexport function relayDialBaseFromSettings(settings: Settings): string {\n if (!settings.selfhostedRelayUrl?.trim()) return \"\";\n const { host, port, tls, path } = relayConfigFromSettings(settings);\n const scheme = tls ? \"wss\" : \"ws\";\n const defaultPort = tls ? 443 : 80;\n const authority = port === defaultPort ? host : `${host}:${port}`;\n return `${scheme}://${authority}${path}`;\n}\n\nfunction controlRpcFactory(bus: EventBus | undefined): () => ControlRpc {\n return () =>\n new NatsControlRpc(async (): Promise<NatsRequestConnection | null> => {\n if (!bus) {\n return null;\n }\n return bus.getRequestConnection();\n });\n}\n\n/** Whether the routing proxy should wrap the Channel-A box: gated by the\n * selfhosted flag (the active pointer + swap are only meaningful then). */\nexport function routingEnabled(settings: Settings): boolean {\n return settings.sandboxSelfhostedEnabled === true;\n}\n\n/**\n * Wrap an established group-box session in a `RoutingSandboxSession` so a\n * Channel-A op routes to the session's currently-active sandbox. Returns the\n * established handle with its `session` replaced by the stable proxy. With the\n * default pointer (active_sandbox_id == null) this routes to the group box\n * unchanged; a selfhosted active pointer routes the op to the machine.\n */\nexport function wrapChannelABoxWithRouting(\n services: ChannelARoutingServices,\n ids: { workspaceId: string; sessionId: string },\n established: EstablishedSandboxSession,\n): EstablishedSandboxSession {\n const { db, settings, bus } = services;\n const resolver = makeActiveBackendResolver({\n workspaceId: ids.workspaceId,\n defaultBackend: established.session as RoutableBackendSession,\n defaultKind: established.backendId,\n getSandbox: async (sandboxId): Promise<RoutableSandbox | null> => {\n const sandbox = await getSandbox(db, ids.workspaceId, sandboxId);\n return sandbox\n ? { id: sandbox.id, kind: sandbox.kind, name: sandbox.name, enrollmentId: sandbox.enrollmentId }\n : null;\n },\n controlRpcFactory: controlRpcFactory(bus),\n relay: relayConfigFromSettings(settings),\n });\n\n const proxy = new RoutingSandboxSession({\n readPointer: async () => {\n const pointer = await readActiveSandbox(db, ids.workspaceId, ids.sessionId);\n return pointer ?? { activeSandboxId: null, activeEpoch: 0 };\n },\n resolveActiveBackend: resolver,\n });\n\n return { ...established, session: proxy };\n}\n","import type { Settings } from \"@opengeni/config\";\nimport { verifyDelegatedAccessToken, type AccessContext, type AccessGrant, type Permission } from \"@opengeni/contracts\";\nimport {\n bootstrapWorkspace,\n ensureManagedAccessForUser,\n findActiveApiKeyByHash,\n getWorkspaceGrant,\n requireWorkspace,\n type Database,\n} from \"@opengeni/db\";\nimport type { Context } from \"hono\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { ManagedAuth } from \"../managed-auth-type\";\n\nconst bearerPrefix = \"Bearer \";\n\nexport type AccessDeps = {\n db: Database;\n settings: Settings;\n managedAuth?: ManagedAuth | null;\n};\n\nexport async function requireAccessContext(c: Context, deps: AccessDeps): Promise<AccessContext> {\n const context = await resolveAccessContext(c, deps);\n if (!context) {\n throw new HTTPException(401, { message: \"authentication required\" });\n }\n return context;\n}\n\nexport async function requireAccessGrant(c: Context, deps: AccessDeps, workspaceId: string, permission?: Permission): Promise<AccessGrant> {\n const context = await requireAccessContext(c, deps);\n const grant = context.workspaceGrants.find((candidate) => candidate.workspaceId === workspaceId)\n ?? await getWorkspaceGrant(deps.db, context.subjectId, workspaceId);\n if (!grant) {\n const workspace = await requireWorkspace(deps.db, workspaceId).catch(() => null);\n if (!workspace) {\n throw new HTTPException(404, { message: \"workspace not found\" });\n }\n throw new HTTPException(403, { message: \"workspace access denied\" });\n }\n if (permission) {\n requirePermission(grant, permission);\n }\n return grant;\n}\n\nexport function requirePermission(grant: AccessGrant, permission: Permission): void {\n if (!hasPermission(grant.permissions, permission)) {\n throw new HTTPException(403, { message: `missing permission: ${permission}` });\n }\n}\n\nexport function hasPermission(permissions: Permission[], permission: Permission): boolean {\n return permissions.includes(permission) || permissions.includes(\"workspace:admin\");\n}\n\nasync function resolveAccessContext(c: Context, deps: AccessDeps): Promise<AccessContext | null> {\n if (deps.settings.productAccessMode === \"local\") {\n return await bootstrapWorkspace(deps.db, {\n accountExternalSource: \"opengeni:local\",\n accountExternalId: \"default\",\n accountName: \"Local\",\n workspaceExternalSource: \"opengeni:local\",\n workspaceExternalId: \"default\",\n workspaceName: \"Local\",\n subjectId: \"dev\",\n subjectLabel: \"Local dev\",\n });\n }\n\n\t if (deps.settings.productAccessMode === \"configured\") {\n\t const delegated = await delegatedAccessContext(c, deps, \"configured\");\n\t if (delegated) {\n\t return delegated;\n\t }\n\t if (deps.settings.delegationSecret) {\n\t return null;\n\t }\n\t return await bootstrapWorkspace(deps.db, {\n\t accountExternalSource: \"opengeni:configured\",\n accountExternalId: \"default\",\n accountName: \"Configured\",\n workspaceExternalSource: \"opengeni:configured\",\n workspaceExternalId: \"default\",\n workspaceName: \"Configured\",\n subjectId: configuredSubject(c),\n subjectLabel: \"Configured key\",\n });\n }\n\n const bearer = bearerToken(c);\n if (bearer) {\n const delegated = await delegatedAccessContext(c, deps, \"managed\", bearer);\n if (delegated) {\n return delegated;\n }\n const apiKey = await findActiveApiKeyByHash(deps.db, await sha256Hex(bearer));\n if (apiKey) {\n const accountPermissions = apiKey.workspaceId\n ? apiKey.permissions.filter((permission) => permission === \"billing:read\" || permission === \"billing:manage\")\n : apiKey.permissions;\n return {\n mode: \"managed\",\n subjectId: `api_key:${apiKey.id}`,\n subjectLabel: apiKey.name,\n accountGrants: [{\n accountId: apiKey.accountId,\n subjectId: `api_key:${apiKey.id}`,\n subjectLabel: apiKey.name,\n permissions: accountPermissions,\n }],\n workspaceGrants: apiKey.workspaceId ? [{\n workspaceId: apiKey.workspaceId,\n accountId: apiKey.accountId,\n subjectId: `api_key:${apiKey.id}`,\n subjectLabel: apiKey.name,\n permissions: apiKey.permissions,\n }] : [],\n defaultAccountId: apiKey.accountId,\n defaultWorkspaceId: apiKey.workspaceId,\n } satisfies AccessContext;\n }\n }\n\n if (deps.managedAuth) {\n const session = await deps.managedAuth.api.getSession({ headers: c.req.raw.headers });\n if (session?.user) {\n return await ensureManagedAccessForUser(deps.db, {\n userId: session.user.id,\n email: session.user.email,\n name: session.user.name,\n });\n }\n }\n\n return null;\n}\n\nasync function delegatedAccessContext(c: Context, deps: AccessDeps, mode: \"configured\" | \"managed\", token = bearerToken(c)): Promise<AccessContext | null> {\n if (!token || !deps.settings.delegationSecret) {\n return null;\n }\n const payload = await verifyDelegatedAccessToken(deps.settings.delegationSecret, token);\n if (!payload) {\n return null;\n }\n return {\n mode,\n subjectId: payload.subjectId,\n ...(payload.subjectLabel ? { subjectLabel: payload.subjectLabel } : {}),\n accountGrants: [{\n accountId: payload.accountId,\n subjectId: payload.subjectId,\n ...(payload.subjectLabel ? { subjectLabel: payload.subjectLabel } : {}),\n permissions: payload.permissions,\n }],\n workspaceGrants: [{\n workspaceId: payload.workspaceId,\n accountId: payload.accountId,\n subjectId: payload.subjectId,\n ...(payload.subjectLabel ? { subjectLabel: payload.subjectLabel } : {}),\n permissions: payload.permissions,\n // sessionId is worker-asserted (HMAC-signed token claim), not agent\n // controlled; it scopes session-bound MCP tools such as goal management.\n metadata: { delegated: true, ...(payload.sessionId ? { sessionId: payload.sessionId } : {}) },\n }],\n defaultAccountId: payload.accountId,\n defaultWorkspaceId: payload.workspaceId,\n };\n}\n\nfunction configuredSubject(c: Context): string {\n const header = c.req.header(\"x-opengeni-subject\");\n return header && header.trim().length > 0 ? `configured:${header.trim()}` : \"configured:key\";\n}\n\nfunction bearerToken(c: Context): string | null {\n const authorization = c.req.header(\"authorization\");\n return authorization?.startsWith(bearerPrefix) ? authorization.slice(bearerPrefix.length) : null;\n}\n\nasync function sha256Hex(value: string): Promise<string> {\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(value));\n return Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n","import { configuredStaticUsageLimits } from \"@opengeni/config\";\nimport type { LimitAction, LimitDecision } from \"@opengeni/contracts\";\nimport {\n countActiveApiKeysForWorkspace,\n countScheduledTasksForWorkspace,\n countWorkspacesForAccount,\n getBillingBalance,\n isCodexBilledTurn,\n recordUsageEvent,\n sumUsageQuantity,\n} from \"@opengeni/db\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { ApiRouteDeps } from \"../dependencies\";\n\nexport type LimitCheckInput = {\n accountId: string;\n workspaceId?: string;\n action: LimitAction;\n quantity?: number;\n // The turn's model id, when the action represents an agent turn. When this is a\n // Codex-billed turn (codex/<slug> + feature enabled + active workspace\n // credential) the turn is paid by the user's ChatGPT/Codex plan and consumes\n // ZERO OpenGeni credits, so the credit-balance + model-cost + token gates are\n // skipped. Non-model infra actions (workspace/api_key/schedule create) leave\n // this undefined and are unaffected.\n model?: string | null;\n};\n\nexport async function requireLimit(deps: ApiRouteDeps, input: LimitCheckInput): Promise<void> {\n const decision = await checkLimit(deps, input);\n if (decision.allowed) {\n return;\n }\n throw new HTTPException(decision.code === \"insufficient_credits\" ? 402 : 429, { message: decision.message });\n}\n\nexport async function checkLimit(deps: ApiRouteDeps, input: LimitCheckInput): Promise<LimitDecision> {\n // Resolve the canonical codex-billed predicate ONCE. Returns false for any\n // action that carries no model (infra caps) or any codex/<slug> model without\n // an active credential — so the bypass never triggers on the prefix alone.\n const codexBilled = input.workspaceId\n ? await isCodexBilledTurn({ db: deps.db, settings: deps.settings, workspaceId: input.workspaceId, model: input.model })\n : false;\n const creditDecision = await checkCreditBalance(deps, input, codexBilled);\n if (!creditDecision.allowed) {\n return creditDecision;\n }\n if (deps.settings.usageLimitsMode !== \"static\" && deps.settings.usageLimitsMode !== \"managed\") {\n return { allowed: true };\n }\n return await checkStaticCaps(deps, input, codexBilled);\n}\n\nasync function checkCreditBalance(deps: ApiRouteDeps, input: LimitCheckInput, codexBilled: boolean): Promise<LimitDecision> {\n if (codexBilled) {\n return { allowed: true }; // paid by the user's ChatGPT/Codex plan — zero OpenGeni credits\n }\n if (!usesCreditLimits(deps) || !isCostlyAction(input.action)) {\n return { allowed: true };\n }\n const balance = await getBillingBalance(deps.db, input.accountId);\n if (balance.balanceMicros > 0) {\n return { allowed: true };\n }\n return { allowed: false, code: \"insufficient_credits\", message: \"insufficient OpenGeni credits\" };\n}\n\nasync function checkStaticCaps(deps: ApiRouteDeps, input: LimitCheckInput, codexBilled: boolean): Promise<LimitDecision> {\n const limits = configuredStaticUsageLimits(deps.settings);\n if (limits.maxMonthlyCostMicrosPerAccount && isCostlyAction(input.action) && !codexBilled) {\n const used = await sumUsageQuantity(deps.db, {\n accountId: input.accountId,\n eventType: \"model.cost\",\n since: startOfUtcMonth(),\n });\n if (used >= limits.maxMonthlyCostMicrosPerAccount) {\n return blocked(\"max_monthly_cost_micros_per_account\", `monthly model cost limit reached (${limits.maxMonthlyCostMicrosPerAccount} micros)`);\n }\n }\n switch (input.action) {\n case \"workspace:create\": {\n if (!limits.maxWorkspacesPerAccount) {\n return { allowed: true };\n }\n const count = await countWorkspacesForAccount(deps.db, input.accountId);\n return count < limits.maxWorkspacesPerAccount\n ? { allowed: true }\n : blocked(\"max_workspaces_per_account\", `workspace limit reached (${limits.maxWorkspacesPerAccount})`);\n }\n case \"api_key:create\": {\n if (!limits.maxApiKeysPerWorkspace || !input.workspaceId) {\n return { allowed: true };\n }\n const count = await countActiveApiKeysForWorkspace(deps.db, input.workspaceId);\n return count < limits.maxApiKeysPerWorkspace\n ? { allowed: true }\n : blocked(\"max_api_keys_per_workspace\", `API key limit reached (${limits.maxApiKeysPerWorkspace})`);\n }\n case \"schedule:create\": {\n if (!limits.maxSchedulesPerWorkspace || !input.workspaceId) {\n return { allowed: true };\n }\n const count = await countScheduledTasksForWorkspace(deps.db, input.workspaceId);\n return count < limits.maxSchedulesPerWorkspace\n ? { allowed: true }\n : blocked(\"max_schedules_per_workspace\", `scheduled task limit reached (${limits.maxSchedulesPerWorkspace})`);\n }\n case \"file:upload\": {\n if (!limits.maxFileUploadBytes || !input.quantity) {\n return { allowed: true };\n }\n return input.quantity <= limits.maxFileUploadBytes\n ? { allowed: true }\n : blocked(\"max_file_upload_bytes\", `file upload exceeds static limit of ${limits.maxFileUploadBytes} bytes`);\n }\n case \"agent_run:create\": {\n if (!limits.maxMonthlyAgentRunsPerWorkspace || !input.workspaceId) {\n return { allowed: true };\n }\n const used = await sumUsageQuantity(deps.db, {\n workspaceId: input.workspaceId,\n eventType: \"agent_run.created\",\n since: startOfUtcMonth(),\n });\n const requested = input.quantity ?? 0;\n return used + requested <= limits.maxMonthlyAgentRunsPerWorkspace\n ? { allowed: true }\n : blocked(\"max_monthly_agent_runs_per_workspace\", `monthly agent run limit reached (${limits.maxMonthlyAgentRunsPerWorkspace})`);\n }\n case \"tokens:consume\": {\n if (codexBilled || !limits.maxMonthlyTokensPerWorkspace || !input.workspaceId) {\n return { allowed: true };\n }\n const used = await sumUsageQuantity(deps.db, {\n workspaceId: input.workspaceId,\n eventType: \"model.tokens\",\n since: startOfUtcMonth(),\n });\n const requested = input.quantity ?? 0;\n return used + requested <= limits.maxMonthlyTokensPerWorkspace\n ? { allowed: true }\n : blocked(\"max_monthly_tokens_per_workspace\", `monthly token limit reached (${limits.maxMonthlyTokensPerWorkspace})`);\n }\n case \"document:index\": {\n if (!limits.maxDocumentIndexedChunksPerWorkspace || !input.workspaceId) {\n return { allowed: true };\n }\n const used = await sumUsageQuantity(deps.db, {\n workspaceId: input.workspaceId,\n eventType: \"document.indexed\",\n since: startOfUtcMonth(),\n });\n const requested = input.quantity ?? 0;\n return used + requested <= limits.maxDocumentIndexedChunksPerWorkspace\n ? { allowed: true }\n : blocked(\"max_document_indexed_chunks_per_workspace\", `monthly document indexing limit reached (${limits.maxDocumentIndexedChunksPerWorkspace} chunks)`);\n }\n }\n}\n\nexport async function recordWorkspaceUsage(deps: ApiRouteDeps, input: {\n accountId: string;\n workspaceId: string;\n subjectId?: string | null;\n eventType:\n | \"agent_run.created\"\n | \"file.uploaded\"\n | \"document.indexed\"\n | \"scheduled_task.fired\";\n quantity: number;\n unit: string;\n sourceResourceType: string;\n sourceResourceId: string;\n idempotencyKey: string;\n}): Promise<void> {\n await recordUsageEvent(deps.db, {\n accountId: input.accountId,\n workspaceId: input.workspaceId,\n subjectId: input.subjectId ?? null,\n eventType: input.eventType,\n quantity: input.quantity,\n unit: input.unit,\n sourceResourceType: input.sourceResourceType,\n sourceResourceId: input.sourceResourceId,\n idempotencyKey: input.idempotencyKey,\n });\n}\n\nfunction usesCreditLimits(deps: ApiRouteDeps): boolean {\n return deps.settings.billingMode === \"stripe\" || deps.settings.usageLimitsMode === \"managed\";\n}\n\nfunction isCostlyAction(action: LimitAction): boolean {\n return action === \"agent_run:create\"\n || action === \"tokens:consume\"\n || action === \"file:upload\"\n || action === \"document:index\";\n}\n\nfunction blocked(code: string, message: string): LimitDecision {\n return { allowed: false, code, message };\n}\n\nfunction startOfUtcMonth(): Date {\n const now = new Date();\n return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { environmentsEncryptionKeyBytes, type Settings } from \"@opengeni/config\";\nimport {\n CapabilityCatalogItem,\n type AccessGrant,\n type CapabilityCatalogResponse,\n type CapabilityInstallation,\n type CapabilityKind,\n type CreateCapabilityCatalogItemRequest,\n type EnableCapabilityRequest,\n} from \"@opengeni/contracts\";\nimport {\n decryptEnvironmentValue,\n decryptedCapabilityHeaders,\n disableCapabilityInstallation,\n enableCapabilityInstallation,\n enablePackInstallation,\n encryptEnvironmentValue,\n getCapabilityCatalogItem,\n getCapabilityInstallation,\n getPackInstallation,\n getStoredCapabilityHeaderCiphertext,\n getWorkspaceEnvironment,\n listCapabilityCatalogItems,\n listCapabilityInstallations,\n listEnabledMcpCapabilityServers,\n listPackInstallations,\n mcpServerIdForCapability,\n updatePackInstallationStatus,\n upsertCapabilityCatalogItem,\n type Database,\n type EnabledMcpCapabilityServer,\n} from \"@opengeni/db\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { validateEnvironmentAttachment } from \"./environments\";\nimport { assertPackSandboxImageCompatible, listCapabilityPacks, listWorkspaceCapabilityPacks, resolveCapabilityPack } from \"./packs\";\n\nconst officialMcpRegistryUrl = \"https://registry.modelcontextprotocol.io\";\nconst firstPartyMcpServerIds = new Set([\"opengeni\", \"files\", \"docs\"]);\nconst mcpRegistryFetchTimeoutMs = 15000;\nconst mcpRegistryMaxPages = 3;\nconst mcpCapabilityProbeTimeoutMs = 15000;\nconst maxMcpCredentialHeaders = 16;\nconst maxMcpCredentialHeaderValueLength = 4096;\n// RFC 9110 field-name token characters.\nconst mcpCredentialHeaderName = /^[A-Za-z0-9!#$%&'*+.^_`|~-]+$/;\n\nexport async function buildCapabilityCatalog(input: {\n db: Database;\n workspaceId: string;\n settings: Settings;\n}): Promise<CapabilityCatalogResponse> {\n const [\n persistedItems,\n capabilityInstallations,\n packInstallations,\n workspacePacks,\n bundledSkills,\n ] = await Promise.all([\n listCapabilityCatalogItems(input.db, input.workspaceId),\n listCapabilityInstallations(input.db, input.workspaceId),\n listPackInstallations(input.db, input.workspaceId),\n listWorkspaceCapabilityPacks(input.db, input.workspaceId),\n discoverBundledSkills(),\n ]);\n const capabilityInstallationById = new Map(capabilityInstallations.map((installation) => [installation.capabilityId, installation]));\n const activePackIds = new Set(packInstallations.filter((installation) => installation.status === \"active\").map((installation) => installation.packId));\n const builtInPackIds = new Set(listCapabilityPacks().map((pack) => pack.id));\n const builtIns = [\n ...workspacePacks.map((pack) => packCatalogItem(pack, builtInPackIds.has(pack.id) ? \"built_in\" : \"manual\")),\n ...configuredMcpCatalogItems(input.settings),\n ...platformApiCatalogItems(),\n ...bundledSkills,\n ];\n const items = dedupeCatalogItems([...builtIns, ...persistedItems])\n .map((item) => applyCapabilityEnablement(item, capabilityInstallationById.get(item.id), activePackIds))\n .sort(compareCatalogItems);\n return {\n items,\n installations: capabilityInstallations,\n };\n}\n\nexport async function createCatalogItem(input: {\n db: Database;\n accountId: string;\n workspaceId: string;\n payload: CreateCapabilityCatalogItemRequest;\n}): Promise<CapabilityCatalogItem> {\n const id = input.payload.id?.trim() || generatedCapabilityId(input.payload);\n if (id.startsWith(\"pack:\")) {\n throw new HTTPException(422, { message: \"packs are managed by OpenGeni and cannot be manually created\" });\n }\n const source = input.payload.source === \"built_in\" || input.payload.source === \"configured\" ? \"manual\" : input.payload.source;\n const metadata = {\n ...input.payload.metadata,\n ...(input.payload.kind === \"mcp\" && input.payload.endpointUrl && !input.payload.metadata.mcpServerId\n ? { mcpServerId: mcpServerIdForCapability(id, input.payload.metadata) }\n : {}),\n };\n return await upsertCapabilityCatalogItem(input.db, {\n accountId: input.accountId,\n workspaceId: input.workspaceId,\n id,\n kind: input.payload.kind,\n source,\n name: input.payload.name.trim(),\n description: input.payload.description?.trim() || null,\n category: input.payload.category.trim() || \"custom\",\n tags: uniqueTags(input.payload.tags),\n homepageUrl: input.payload.homepageUrl ?? null,\n endpointUrl: input.payload.endpointUrl ?? null,\n installUrl: input.payload.installUrl ?? null,\n authModel: input.payload.authModel?.trim() || null,\n metadata,\n });\n}\n\nexport async function enableCapability(input: {\n db: Database;\n grant: AccessGrant;\n accountId: string;\n workspaceId: string;\n settings: Settings;\n capabilityId: string;\n payload: EnableCapabilityRequest;\n probeMcpServer?: McpCapabilityProbe;\n}): Promise<CapabilityInstallation> {\n const item = await requireCatalogItem(input.db, input.workspaceId, input.settings, input.capabilityId);\n if (item.kind === \"mcp\" && !item.runtime.available) {\n throw new HTTPException(422, { message: \"MCP capabilities need a remote streamable HTTP endpoint before they can be enabled\" });\n }\n let installationMetadata = input.payload.metadata;\n // Credential-header storage is written exclusively by this flow; strip the\n // reserved keys from caller-provided config so the stored shape stays\n // trustworthy and no plaintext credentials sneak in through config.headers.\n const installationConfig: Record<string, unknown> = { ...input.payload.config };\n delete installationConfig.headers;\n delete installationConfig.headersEncrypted;\n delete installationConfig.headerNames;\n if (item.kind === \"mcp\") {\n const headers = await resolveMcpCredentialHeaders(input, item);\n assertRequiredMcpCredentialHeaders(item, headers);\n installationMetadata = {\n ...installationMetadata,\n ...await validateMcpCapabilityConnection(item, input.probeMcpServer, headers ?? undefined),\n };\n if (headers) {\n const key = requireCapabilityHeaderEncryption(input.settings);\n installationConfig.headersEncrypted = Object.fromEntries(\n Object.entries(headers).map(([name, value]) => [name, encryptEnvironmentValue(key, value)]),\n );\n }\n }\n if (item.kind === \"pack\") {\n const packId = packIdFromCapabilityId(item.id);\n const pack = await resolveCapabilityPack(input.db, input.workspaceId, packId);\n if (!pack) {\n throw new HTTPException(404, { message: \"pack not found\" });\n }\n await assertPackSandboxImageCompatible(input.db, input.workspaceId, pack);\n // The unified capability-enable path accepts an initial environment\n // attachment (`payload.environmentId`), mirroring POST /packs/:id/enable:\n // a request-supplied id is validated as a fresh attachment, otherwise the\n // attachment stored by a previous enable is preserved and re-validated.\n const existing = await getPackInstallation(input.db, input.workspaceId, packId);\n const storedEnvironmentId = typeof existing?.metadata.environmentId === \"string\" ? existing.metadata.environmentId : undefined;\n const requestedEnvironmentId = input.payload.environmentId;\n const environmentId = requestedEnvironmentId ?? storedEnvironmentId;\n if (pack.environment?.required && !environmentId) {\n throw new HTTPException(422, {\n message: `pack ${packId} requires an environment attachment; pass environmentId`,\n });\n }\n if (environmentId) {\n if (requestedEnvironmentId) {\n // A fresh attachment: validate it like the packs enable endpoint does.\n // The grant holds workspace:admin here, which implies environments:use,\n // so the attachment authorization succeeds for this caller.\n const environment = await validateEnvironmentAttachment(\n { settings: input.settings, db: input.db },\n input.grant,\n input.workspaceId,\n requestedEnvironmentId,\n );\n const missing = (pack.environment?.requiredVariables ?? [])\n .filter((name) => !environment.variables.some((variable) => variable.name === name));\n if (missing.length > 0) {\n throw new HTTPException(422, { message: `environment is missing required variable(s): ${missing.join(\", \")}` });\n }\n } else {\n // The stored attachment was authorized at pack-enable time, but the\n // environment may have been deleted or its variables changed since;\n // re-validate it like the packs enable endpoint does.\n const environment = await getWorkspaceEnvironment(input.db, input.workspaceId, environmentId);\n if (!environment) {\n throw new HTTPException(422, {\n message: `the stored environment attachment for pack ${packId} no longer exists; re-enable it with environmentId`,\n });\n }\n const missing = (pack.environment?.requiredVariables ?? [])\n .filter((name) => !environment.variables.some((variable) => variable.name === name));\n if (missing.length > 0) {\n throw new HTTPException(422, { message: `environment is missing required variable(s): ${missing.join(\", \")}` });\n }\n }\n }\n await enablePackInstallation(input.db, {\n accountId: input.accountId,\n workspaceId: input.workspaceId,\n packId,\n metadata: {\n ...input.payload.metadata,\n packVersion: pack.version,\n ...(environmentId ? { environmentId } : {}),\n },\n });\n }\n return await enableCapabilityInstallation(input.db, {\n accountId: input.accountId,\n workspaceId: input.workspaceId,\n capabilityId: item.id,\n kind: item.kind,\n config: installationConfig,\n metadata: installationMetadata,\n });\n}\n\n/**\n * Resolves the plaintext credential headers an MCP enable should use: the\n * validated headers from the request when provided, otherwise headers stored\n * encrypted by a previous enable (so re-enabling never requires re-pasting\n * credentials). Returns null when neither exists.\n */\nasync function resolveMcpCredentialHeaders(\n input: { db: Database; workspaceId: string; settings: Settings; payload: EnableCapabilityRequest },\n item: CapabilityCatalogItem,\n): Promise<Record<string, string> | null> {\n const provided = normalizedMcpCredentialHeaders(input.payload.headers);\n if (provided) {\n // Validate the key is configured before probing so a misconfigured\n // deployment fails fast instead of after a successful remote probe.\n requireCapabilityHeaderEncryption(input.settings);\n return provided;\n }\n const storedCiphertext = await getStoredCapabilityHeaderCiphertext(input.db, input.workspaceId, item.id);\n if (!storedCiphertext) {\n return null;\n }\n const key = requireCapabilityHeaderEncryption(input.settings);\n try {\n return Object.fromEntries(Object.entries(storedCiphertext).map(([name, value]) => [name, decryptEnvironmentValue(key, value)]));\n } catch {\n throw new HTTPException(422, {\n message: `stored credential headers for \"${item.name}\" could not be decrypted; supply them again in the enable request \"headers\" field`,\n });\n }\n}\n\nfunction normalizedMcpCredentialHeaders(headers: Record<string, string>): Record<string, string> | null {\n const entries = Object.entries(headers).map(([name, value]) => [name.trim(), value] as const).filter(([name]) => name.length > 0);\n if (entries.length === 0) {\n return null;\n }\n if (entries.length > maxMcpCredentialHeaders) {\n throw new HTTPException(422, { message: `an MCP capability supports at most ${maxMcpCredentialHeaders} credential headers` });\n }\n const seen = new Set<string>();\n for (const [name, value] of entries) {\n if (!mcpCredentialHeaderName.test(name)) {\n throw new HTTPException(422, { message: `invalid credential header name: ${name}` });\n }\n const lower = name.toLowerCase();\n if (seen.has(lower)) {\n throw new HTTPException(422, { message: `duplicate credential header name: ${name}` });\n }\n seen.add(lower);\n if (value.length === 0 || value.length > maxMcpCredentialHeaderValueLength) {\n throw new HTTPException(422, { message: `credential header ${name} must be 1-${maxMcpCredentialHeaderValueLength} characters` });\n }\n // RFC 9110 §5.5: field values are HTAB / printable characters — reject\n // all other control characters (they would also fail at the HTTP client).\n // eslint-disable-next-line no-control-regex\n if (/[\\u0000-\\u0008\\u000A-\\u001F\\u007F]/.test(value)) {\n throw new HTTPException(422, { message: `credential header ${name} contains forbidden control characters` });\n }\n }\n return Object.fromEntries(entries);\n}\n\nfunction assertRequiredMcpCredentialHeaders(item: CapabilityCatalogItem, headers: Record<string, string> | null): void {\n const required = requiredCapabilityHeaders(item.metadata);\n const names = new Set(Object.keys(headers ?? {}).map((name) => name.toLowerCase()));\n const missing = required.filter((name) => !names.has(name.toLowerCase()));\n if (missing.length > 0) {\n throw new HTTPException(422, {\n message: `MCP capability \"${item.name}\" requires credential header(s) ${missing.join(\", \")}; pass them in the enable request \"headers\" field`,\n });\n }\n if (item.authModel && names.size === 0) {\n throw new HTTPException(422, {\n message: `MCP capability \"${item.name}\" requires credentials; pass them in the enable request \"headers\" field`,\n });\n }\n}\n\nfunction requiredCapabilityHeaders(metadata: Record<string, unknown>): string[] {\n const value = metadata.requiredHeaders;\n if (!Array.isArray(value)) {\n return [];\n }\n return value.filter((name): name is string => typeof name === \"string\" && name.trim().length > 0).map((name) => name.trim());\n}\n\nfunction requireCapabilityHeaderEncryption(settings: Settings): Uint8Array {\n const key = environmentsEncryptionKeyBytes(settings);\n if (!key) {\n throw new HTTPException(503, { message: \"MCP credential headers require OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY\" });\n }\n return key;\n}\n\nexport type McpCapabilityProbeInput = {\n id: string;\n name: string;\n url: string;\n timeoutMs: number;\n headers?: Record<string, string>;\n};\n\nexport type McpCapabilityProbeResult = {\n toolCount: number;\n};\n\nexport type McpCapabilityProbe = (input: McpCapabilityProbeInput) => Promise<McpCapabilityProbeResult>;\n\nexport async function validateMcpCapabilityConnection(\n item: CapabilityCatalogItem,\n probe: McpCapabilityProbe = probeStreamableHttpMcpServer,\n headers?: Record<string, string>,\n): Promise<Record<string, unknown>> {\n if (item.kind !== \"mcp\") {\n return {};\n }\n if (!item.endpointUrl || !item.runtime.mcpServerId) {\n throw new HTTPException(422, { message: \"MCP capabilities need a remote streamable HTTP endpoint before they can be enabled\" });\n }\n try {\n const result = await probe({\n id: item.runtime.mcpServerId,\n name: item.name,\n url: item.endpointUrl,\n timeoutMs: mcpCapabilityProbeTimeoutMs,\n ...(headers ? { headers } : {}),\n });\n return {\n mcpConnectivity: {\n status: \"ok\",\n checkedAt: new Date().toISOString(),\n toolCount: result.toolCount,\n },\n };\n } catch (error) {\n throw new HTTPException(422, {\n message: `MCP capability \"${item.name}\" could not be enabled because OpenGeni could not initialize ${item.endpointUrl}: ${mcpProbeErrorMessage(error)}`,\n });\n }\n}\n\nasync function probeStreamableHttpMcpServer(input: McpCapabilityProbeInput): Promise<McpCapabilityProbeResult> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), input.timeoutMs);\n const client = new Client({ name: \"opengeni-capability-probe\", version: \"0.1.0\" }, { capabilities: {} });\n try {\n const transport = new StreamableHTTPClientTransport(new URL(input.url), {\n requestInit: {\n signal: controller.signal,\n ...(input.headers ? { headers: input.headers } : {}),\n },\n });\n await client.connect(transport as unknown as Transport, { timeout: input.timeoutMs, maxTotalTimeout: input.timeoutMs });\n const tools = await client.listTools(undefined, { timeout: input.timeoutMs, maxTotalTimeout: input.timeoutMs });\n return { toolCount: tools.tools.length };\n } finally {\n clearTimeout(timeout);\n await client.close().catch(() => undefined);\n }\n}\n\nfunction mcpProbeErrorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.replace(/\\s+/g, \" \").trim().slice(0, 500) || \"unknown error\";\n}\n\nexport async function disableCapability(input: {\n db: Database;\n accountId: string;\n workspaceId: string;\n settings: Settings;\n capabilityId: string;\n}): Promise<CapabilityInstallation> {\n const item = await requireCatalogItem(input.db, input.workspaceId, input.settings, input.capabilityId);\n if ((item.source === \"built_in\" || item.source === \"configured\") && item.kind !== \"pack\") {\n throw new HTTPException(409, { message: \"built-in and configured capabilities are always available; remove them from configuration to disable them\" });\n }\n if (item.kind === \"pack\") {\n await updatePackInstallationStatus(input.db, input.workspaceId, packIdFromCapabilityId(item.id), \"disabled\").catch(() => undefined);\n if (!await getCapabilityInstallation(input.db, input.workspaceId, item.id)) {\n await enableCapabilityInstallation(input.db, {\n accountId: input.accountId,\n workspaceId: input.workspaceId,\n capabilityId: item.id,\n kind: \"pack\",\n metadata: {},\n config: {},\n });\n }\n } else if (!await getCapabilityInstallation(input.db, input.workspaceId, item.id)) {\n throw new HTTPException(409, { message: \"capability is not currently enabled\" });\n }\n return await disableCapabilityInstallation(input.db, input.workspaceId, item.id);\n}\n\nexport async function settingsWithEnabledCapabilityMcpServers(db: Database, workspaceId: string, settings: Settings): Promise<Settings> {\n const enabled = await listEnabledMcpCapabilityServers(db, workspaceId);\n return settingsWithMcpCapabilityServers(settings, enabled);\n}\n\nexport function settingsWithMcpCapabilityServers(settings: Settings, enabled: EnabledMcpCapabilityServer[]): Settings {\n if (enabled.length === 0) {\n return settings;\n }\n const encryptionKey = environmentsEncryptionKeyBytes(settings);\n const existingIds = new Set(settings.mcpServers.map((server) => server.id));\n const dynamicServers = enabled\n .filter((server) => !existingIds.has(server.id))\n .flatMap((server) => {\n const headers = decryptedCapabilityHeaders(server, encryptionKey);\n if (headers === \"unavailable\") {\n // Without its credential headers this server can only fail auth at\n // connect time and break agent turns; leave it out of the run.\n return [];\n }\n return [{\n id: server.id,\n name: server.name,\n url: server.url,\n ...(server.allowedTools ? { allowedTools: server.allowedTools } : {}),\n ...(server.timeoutMs ? { timeoutMs: server.timeoutMs } : {}),\n cacheToolsList: server.cacheToolsList ?? false,\n ...(headers ? { headers } : {}),\n }];\n });\n return dynamicServers.length ? { ...settings, mcpServers: [...settings.mcpServers, ...dynamicServers] } : settings;\n}\n\nexport async function discoverMcpRegistryCapabilities(input: {\n query?: string;\n limit?: number;\n fetchImpl?: McpRegistryFetch;\n timeoutMs?: number;\n}): Promise<CapabilityCatalogItem[]> {\n const query = (input.query ?? \"\").trim().toLowerCase();\n const limit = Math.min(100, Math.max(1, Math.floor(input.limit ?? 50)));\n const items: CapabilityCatalogItem[] = [];\n const seen = new Set<string>();\n const fetchOptions: { fetchImpl?: McpRegistryFetch; timeoutMs?: number } = {};\n if (input.fetchImpl) {\n fetchOptions.fetchImpl = input.fetchImpl;\n }\n if (input.timeoutMs !== undefined) {\n fetchOptions.timeoutMs = input.timeoutMs;\n }\n let cursor: string | undefined;\n let pages = 0;\n\n while (items.length < limit && pages < mcpRegistryMaxPages) {\n pages += 1;\n const url = new URL(\"/v0.1/servers\", officialMcpRegistryUrl);\n url.searchParams.set(\"limit\", String(limit));\n url.searchParams.set(\"version\", \"latest\");\n if (query) {\n url.searchParams.set(\"search\", query);\n }\n if (cursor) {\n url.searchParams.set(\"cursor\", cursor);\n }\n const page = await fetchMcpRegistryPage(url, fetchOptions);\n for (const entry of page.servers ?? []) {\n const item = mcpRegistryEntryToCatalogItem(entry);\n if (!item || seen.has(item.id)) {\n continue;\n }\n if (query && !catalogSearchText(item).includes(query)) {\n continue;\n }\n seen.add(item.id);\n items.push(item);\n if (items.length >= limit) {\n break;\n }\n }\n cursor = typeof page.metadata?.nextCursor === \"string\" ? page.metadata.nextCursor : undefined;\n if (!cursor) {\n break;\n }\n }\n\n return items;\n}\n\nexport { officialMcpRegistryUrl };\n\ntype McpRegistryFetch = (input: URL, init?: RequestInit) => Promise<Response>;\n\nasync function fetchMcpRegistryPage(url: URL, options: {\n fetchImpl?: McpRegistryFetch;\n timeoutMs?: number;\n} = {}): Promise<McpRegistryPage> {\n const fetchImpl = options.fetchImpl ?? fetch;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? mcpRegistryFetchTimeoutMs);\n try {\n const response = await fetchImpl(url, { signal: controller.signal });\n if (!response.ok) {\n throw new HTTPException(502, { message: `MCP registry returned ${response.status}` });\n }\n return await response.json() as McpRegistryPage;\n } catch (error) {\n if (error instanceof HTTPException) {\n throw error;\n }\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new HTTPException(504, { message: \"MCP registry request timed out\" });\n }\n throw new HTTPException(502, {\n message: `MCP registry request failed: ${error instanceof Error ? error.message : String(error)}`,\n });\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function requireCatalogItem(db: Database, workspaceId: string, settings: Settings, capabilityId: string): Promise<CapabilityCatalogItem> {\n const catalog = await buildCapabilityCatalog({ db, workspaceId, settings });\n const item = catalog.items.find((candidate) => candidate.id === capabilityId) ?? await getCapabilityCatalogItem(db, workspaceId, capabilityId);\n if (!item) {\n throw new HTTPException(404, { message: \"capability not found\" });\n }\n return item;\n}\n\nfunction packCatalogItem(pack: ReturnType<typeof listCapabilityPacks>[number], source: \"built_in\" | \"manual\"): CapabilityCatalogItem {\n return CapabilityCatalogItem.parse({\n id: `pack:${pack.id}`,\n kind: \"pack\",\n source,\n name: pack.name,\n description: pack.description,\n category: pack.category,\n tags: [pack.role, pack.category, \"pack\"],\n tools: pack.tools,\n runtime: {\n available: true,\n notes: \"Enables role-scoped tools, connectors, knowledge, and scheduled-task templates.\",\n },\n metadata: {\n packId: pack.id,\n version: pack.version,\n connectors: pack.connectors,\n knowledge: pack.knowledge,\n scheduledTaskTemplates: pack.scheduledTaskTemplates,\n // Runtime composition surface only: skill names, never file content.\n ...(pack.sandboxImage ? { sandboxImage: pack.sandboxImage } : {}),\n ...(pack.skills.length > 0 ? { skills: pack.skills.map((skill) => skill.name) } : {}),\n ...pack.metadata,\n },\n });\n}\n\nfunction configuredMcpCatalogItems(settings: Settings): CapabilityCatalogItem[] {\n return settings.mcpServers.map((server) => CapabilityCatalogItem.parse({\n id: `mcp:${server.id}`,\n kind: \"mcp\",\n source: firstPartyMcpServerIds.has(server.id) ? \"built_in\" : \"configured\",\n name: server.name ?? server.id,\n description: firstPartyMcpDescription(server.id),\n category: firstPartyMcpServerIds.has(server.id) ? \"platform\" : \"configured\",\n tags: [\"mcp\", ...(server.allowedTools?.length ? [\"limited-tools\"] : [])],\n endpointUrl: server.url,\n tools: [{ kind: \"mcp\", id: server.id }],\n runtime: {\n available: true,\n mcpServerId: server.id,\n transport: \"streamable-http\",\n notes: firstPartyMcpServerIds.has(server.id) ? \"Available from OpenGeni runtime configuration.\" : \"Configured through OPENGENI_MCP_SERVERS.\",\n },\n metadata: {\n mcpServerId: server.id,\n allowedTools: server.allowedTools ?? [],\n cacheToolsList: server.cacheToolsList,\n },\n }));\n}\n\nfunction platformApiCatalogItems(): CapabilityCatalogItem[] {\n return [\n {\n id: \"api:github-app\",\n name: \"GitHub App\",\n description: \"Repository discovery, scoped clone tokens, pushes, and pull requests.\",\n category: \"source-control\",\n tags: [\"api\", \"github\", \"repositories\"],\n endpointPath: \"/v1/workspaces/{workspaceId}/github/app\",\n },\n {\n id: \"api:documents\",\n name: \"Document Knowledge Base\",\n description: \"Upload, index, search, and attach knowledge bases to agents.\",\n category: \"knowledge\",\n tags: [\"api\", \"documents\", \"knowledge\"],\n endpointPath: \"/v1/workspaces/{workspaceId}/document-bases\",\n },\n {\n id: \"api:social\",\n name: \"Social Accounts\",\n description: \"Connect social accounts and ingest posts for marketing agents.\",\n category: \"marketing\",\n tags: [\"api\", \"social\", \"marketing\"],\n endpointPath: \"/v1/workspaces/{workspaceId}/social/connections\",\n },\n {\n id: \"api:scheduled-tasks\",\n name: \"Scheduled Tasks\",\n description: \"Run agents once, on intervals, or on calendar schedules.\",\n category: \"automation\",\n tags: [\"api\", \"schedules\", \"agents\"],\n endpointPath: \"/v1/workspaces/{workspaceId}/scheduled-tasks\",\n },\n ].map((item) => CapabilityCatalogItem.parse({\n id: item.id,\n name: item.name,\n description: item.description,\n category: item.category,\n tags: item.tags,\n kind: \"api\",\n source: \"built_in\",\n runtime: {\n available: true,\n notes: \"Available through the OpenGeni API.\",\n },\n metadata: {\n endpointPath: item.endpointPath,\n },\n }));\n}\n\nasync function discoverBundledSkills(): Promise<CapabilityCatalogItem[]> {\n const skillsDir = new URL(\"../../../../packages/runtime/src/bundled_hashicorp_terraform_skills/\", import.meta.url);\n try {\n const entries = await readdir(skillsDir, { withFileTypes: true });\n const skills = await Promise.all(entries\n .filter((entry) => entry.isDirectory())\n .map(async (entry) => {\n const skill = await readSkillMetadata(new URL(`${entry.name}/SKILL.md`, skillsDir), entry.name);\n return CapabilityCatalogItem.parse({\n id: `skill:${entry.name}`,\n kind: \"skill\",\n source: \"built_in\",\n name: skill.name,\n description: skill.description,\n category: skill.category,\n tags: [\"skill\", skill.category],\n runtime: {\n available: true,\n notes: \"Bundled into the sandbox skill library.\",\n },\n metadata: {\n path: `packages/runtime/src/bundled_hashicorp_terraform_skills/${entry.name}/SKILL.md`,\n },\n });\n }));\n return skills;\n } catch {\n return [];\n }\n}\n\nasync function readSkillMetadata(url: URL, fallbackName: string): Promise<{ name: string; description: string | null; category: string }> {\n const content = await readFile(url, \"utf8\");\n const frontMatter = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n const frontMatterBody = frontMatter?.[1] ?? \"\";\n const name = frontMatterBody.match(/^name:\\s*(.+)$/m)?.[1]?.trim() || fallbackName;\n const blockDescription = frontMatterBody.match(/^description:\\s*>-\\s*\\n([\\s\\S]*?)(?:\\n[a-zA-Z_-]+:|\\n?$)/m)?.[1]\n ?.split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .join(\" \");\n const inlineDescription = frontMatterBody.match(/^description:\\s*(?!>-\\s*$)(.+)$/m)?.[1]?.trim();\n const description = blockDescription\n || inlineDescription\n || content.match(/^#\\s+(.+)$/m)?.[1]?.trim()\n || null;\n const lower = `${fallbackName} ${name} ${description ?? \"\"}`.toLowerCase();\n const category = lower.includes(\"social\") || lower.includes(\"marketing\")\n ? \"marketing\"\n : lower.includes(\"checkov\") || lower.includes(\"terraform\") || lower.includes(\"azure\")\n ? \"infrastructure\"\n : \"general\";\n return { name, description, category };\n}\n\nfunction applyCapabilityEnablement(\n item: CapabilityCatalogItem,\n installation: CapabilityInstallation | undefined,\n activePackIds: Set<string>,\n): CapabilityCatalogItem {\n if (item.kind === \"pack\") {\n // Pack enablement lives in pack_installations regardless of whether the\n // pack is built in or registered from a workspace manifest.\n const enabled = activePackIds.has(packIdFromCapabilityId(item.id)) || installation?.status === \"active\";\n return {\n ...item,\n enabled,\n enabledReason: enabled ? \"enabled\" : null,\n };\n }\n if (item.source === \"built_in\" || item.source === \"configured\") {\n return {\n ...item,\n enabled: true,\n enabledReason: item.source === \"configured\" ? \"configured\" : \"built in\",\n };\n }\n const activeInstallation = installation?.status === \"active\";\n const enabled = !!activeInstallation && capabilityInstallationRuntimeReady(item, installation);\n return {\n ...item,\n enabled,\n enabledReason: enabled ? \"enabled\" : null,\n };\n}\n\nfunction dedupeCatalogItems(items: CapabilityCatalogItem[]): CapabilityCatalogItem[] {\n const byId = new Map<string, CapabilityCatalogItem>();\n for (const item of items) {\n byId.set(item.id, item);\n }\n return [...byId.values()];\n}\n\nfunction compareCatalogItems(a: CapabilityCatalogItem, b: CapabilityCatalogItem): number {\n return `${a.kind}:${a.category}:${a.name}`.localeCompare(`${b.kind}:${b.category}:${b.name}`);\n}\n\nfunction firstPartyMcpDescription(id: string): string | null {\n if (id === \"opengeni\") {\n return \"First-party OpenGeni MCP tools for files, documents, schedules, and social analysis.\";\n }\n if (id === \"docs\") {\n return \"Document-base search tools for indexed knowledge.\";\n }\n if (id === \"files\") {\n return \"File download URL tools for sandbox-mounted file resources.\";\n }\n return null;\n}\n\nfunction generatedCapabilityId(payload: CreateCapabilityCatalogItemRequest): string {\n const source = [payload.kind, payload.name, payload.endpointUrl ?? payload.installUrl ?? payload.homepageUrl ?? \"\"].join(\":\");\n return `${payload.kind}:${slugify(payload.name)}-${shortHash(source)}`;\n}\n\nfunction publicRegistryCapabilityId(name: string, version: string, endpointUrl: string): string {\n return `mcp-registry:${slugify(name)}-${shortHash(`${name}:${version}:${endpointUrl}`)}`;\n}\n\nfunction packIdFromCapabilityId(capabilityId: string): string {\n return capabilityId.replace(/^pack:/, \"\");\n}\n\nfunction uniqueTags(tags: string[]): string[] {\n return [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];\n}\n\nfunction slugify(value: string): string {\n return value.toLowerCase().replace(/[^a-z0-9_-]+/g, \"-\").replace(/^-+|-+$/g, \"\").slice(0, 60) || \"capability\";\n}\n\nfunction shortHash(value: string): string {\n let hash = 0x811c9dc5;\n for (let index = 0; index < value.length; index += 1) {\n hash ^= value.charCodeAt(index);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(36).padStart(7, \"0\").slice(0, 7);\n}\n\ntype McpRegistryPage = {\n servers?: McpRegistryEntry[];\n metadata?: {\n nextCursor?: string;\n };\n};\n\ntype McpRegistryEntry = {\n server?: {\n name?: string;\n title?: string;\n description?: string;\n version?: string;\n websiteUrl?: string;\n repository?: {\n url?: string;\n };\n remotes?: Array<{\n type?: string;\n url?: string;\n headers?: Array<{\n name?: string;\n description?: string;\n isRequired?: boolean;\n isSecret?: boolean;\n }>;\n }>;\n packages?: unknown[];\n };\n _meta?: {\n \"io.modelcontextprotocol.registry/official\"?: {\n status?: string;\n isLatest?: boolean;\n updatedAt?: string;\n };\n };\n};\n\ntype McpRegistryRemote = NonNullable<NonNullable<McpRegistryEntry[\"server\"]>[\"remotes\"]>[number];\n\nfunction mcpRegistryEntryToCatalogItem(entry: McpRegistryEntry): CapabilityCatalogItem | null {\n const server = entry.server;\n if (!server?.name) {\n return null;\n }\n const official = entry._meta?.[\"io.modelcontextprotocol.registry/official\"];\n if (official?.status && official.status !== \"active\") {\n return null;\n }\n if (official?.isLatest === false) {\n return null;\n }\n const remote = server.remotes?.find((candidate) => candidate.type === \"streamable-http\" && candidate.url);\n const endpointUrl = validUrl(remote?.url);\n if (!remote || !endpointUrl) {\n return null;\n }\n const version = server.version ?? \"latest\";\n const id = publicRegistryCapabilityId(server.name, version, endpointUrl);\n const homepageUrl = validUrl(server.websiteUrl) ?? validUrl(server.repository?.url);\n const requiredHeaders = requiredRemoteHeaders(remote);\n const mcpServerId = mcpServerIdForCapability(id, {});\n return CapabilityCatalogItem.parse({\n id,\n kind: \"mcp\",\n source: \"public_registry\",\n name: server.title || server.name,\n description: server.description ?? null,\n category: \"public-mcp\",\n tags: [\"mcp\", \"public\", \"registry\", ...(requiredHeaders.length ? [\"requires-credentials\"] : [])],\n homepageUrl,\n endpointUrl,\n installUrl: homepageUrl,\n authModel: requiredHeaders.length ? \"credential_ref\" : null,\n tools: [{ kind: \"mcp\", id: mcpServerId }],\n runtime: {\n available: true,\n mcpServerId,\n transport: \"streamable-http\",\n notes: requiredHeaders.length === 0\n ? \"Remote MCP server from the official MCP Registry.\"\n : `This MCP requires credential header(s) ${requiredHeaders.join(\", \")} supplied in the enable request.`,\n },\n metadata: {\n registry: \"official_mcp_registry\",\n registryName: server.name,\n version,\n updatedAt: official?.updatedAt,\n packages: server.packages ?? [],\n requiredHeaders,\n },\n });\n}\n\nfunction requiredRemoteHeaders(remote: McpRegistryRemote): string[] {\n return (remote.headers ?? [])\n .filter((header) => header.name && header.isRequired !== false)\n .map((header) => header.name!.trim())\n .filter(Boolean);\n}\n\nfunction validUrl(value: string | undefined): string | null {\n if (!value) {\n return null;\n }\n try {\n return new URL(value).toString();\n } catch {\n return null;\n }\n}\n\nfunction catalogSearchText(item: CapabilityCatalogItem): string {\n return [\n item.name,\n item.description,\n item.category,\n ...item.tags,\n item.endpointUrl,\n item.homepageUrl,\n item.installUrl,\n JSON.stringify(item.metadata),\n ].filter(Boolean).join(\" \").toLowerCase();\n}\n\nfunction capabilityInstallationRuntimeReady(\n item: CapabilityCatalogItem,\n installation: CapabilityInstallation | undefined,\n): boolean {\n if (!installation || item.kind !== \"mcp\") {\n return !!installation;\n }\n if (!item.runtime.available) {\n return false;\n }\n if (!storedCredentialHeadersSatisfy(item, installation)) {\n return false;\n }\n const connectivity = installation.metadata.mcpConnectivity;\n return !!connectivity && typeof connectivity === \"object\" && \"status\" in connectivity && connectivity.status === \"ok\";\n}\n\n/**\n * Checks the redacted installation config (header names only) against the\n * capability's declared credential requirements.\n */\nfunction storedCredentialHeadersSatisfy(item: CapabilityCatalogItem, installation: CapabilityInstallation): boolean {\n const storedNames = new Set(\n (Array.isArray(installation.config.headerNames) ? installation.config.headerNames : [])\n .filter((name): name is string => typeof name === \"string\")\n .map((name) => name.toLowerCase()),\n );\n const required = requiredCapabilityHeaders(item.metadata);\n if (required.some((name) => !storedNames.has(name.toLowerCase()))) {\n return false;\n }\n return !item.authModel || storedNames.size > 0;\n}\n","import { environmentsEncryptionKeyBytes, type Settings } from \"@opengeni/config\";\nimport type { AccessGrant, WorkspaceEnvironment } from \"@opengeni/contracts\";\nimport {\n getWorkspaceEnvironment,\n recordAuditEvent,\n type Database,\n} from \"@opengeni/db\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { requirePermission } from \"../access\";\n\nexport const MAX_ENVIRONMENTS_PER_WORKSPACE = 25;\nexport const MAX_VARIABLES_PER_ENVIRONMENT = 100;\n\n// Names the platform itself injects into sandboxes (sandboxEnvironmentForRun,\n// collectGitIdentityEnvironment) plus loader/startup-injection vectors. These\n// can never be set as workspace environment variables, so the run-scoped\n// GitHub auth block and git identity always win without silent collisions.\nconst reservedExactNames = new Set([\n \"HOME\",\n \"PATH\",\n \"SHELL\",\n \"USER\",\n \"LOGNAME\",\n \"TMPDIR\",\n \"IFS\",\n \"ENV\",\n \"BASH_ENV\",\n \"NODE_OPTIONS\",\n \"PYTHONPATH\",\n \"PYTHONSTARTUP\",\n \"PERL5OPT\",\n \"PERL5LIB\",\n \"GH_TOKEN\",\n \"GITHUB_TOKEN\",\n \"GIT_ASKPASS\",\n \"GIT_TERMINAL_PROMPT\",\n]);\n\nconst reservedPrefixes = [\n \"OPENGENI_\",\n \"GIT_CONFIG_\",\n \"GIT_AUTHOR_\",\n \"GIT_COMMITTER_\",\n \"LD_\",\n \"DYLD_\",\n];\n\nexport function assertAllowedEnvironmentVariableName(name: string): void {\n if (reservedExactNames.has(name) || reservedPrefixes.some((prefix) => name.startsWith(prefix))) {\n throw new HTTPException(422, { message: `reserved environment variable name: ${name}` });\n }\n}\n\nexport function requireEnvironmentEncryption(settings: Settings): Uint8Array {\n const key = environmentsEncryptionKeyBytes(settings);\n if (!key) {\n throw new HTTPException(503, { message: \"workspace environments require OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY\" });\n }\n return key;\n}\n\nexport async function requireEnvironmentForApi(db: Database, workspaceId: string, environmentId: string): Promise<WorkspaceEnvironment> {\n const environment = await getWorkspaceEnvironment(db, workspaceId, environmentId);\n if (!environment) {\n throw new HTTPException(404, { message: \"environment not found\" });\n }\n return environment;\n}\n\n/**\n * Validates an environment attachment supplied in a request payload (session\n * create, scheduled task create/update, pack enable). Requires the\n * `environments:use` permission unless the attachment was already authorized\n * (pack-installation-inherited attachments), and maps a missing or\n * cross-workspace environment to 422 because the id is payload, not the route\n * target. RLS plus the workspace_id clause make cross-workspace ids\n * indistinguishable from missing ones.\n */\nexport async function validateEnvironmentAttachment(\n deps: { settings: Settings; db: Database },\n grant: AccessGrant,\n workspaceId: string,\n environmentId: string,\n options: { preauthorized?: boolean } = {},\n): Promise<WorkspaceEnvironment> {\n requireEnvironmentEncryption(deps.settings);\n if (!options.preauthorized) {\n requirePermission(grant, \"environments:use\");\n }\n const environment = await getWorkspaceEnvironment(deps.db, workspaceId, environmentId);\n if (!environment) {\n throw new HTTPException(422, { message: \"unknown environmentId\" });\n }\n return environment;\n}\n\nexport async function recordEnvironmentAuditEvent(db: Database, input: {\n grant: AccessGrant;\n action: \"environment.created\" | \"environment.updated\" | \"environment.deleted\" | \"environment.variable.set\" | \"environment.variable.deleted\";\n environmentId: string;\n variableName?: string;\n}): Promise<void> {\n await recordAuditEvent(db, {\n accountId: input.grant.accountId,\n workspaceId: input.grant.workspaceId,\n subjectId: input.grant.subjectId,\n action: input.action,\n targetType: \"workspace_environment\",\n targetId: input.environmentId,\n metadata: {\n environmentId: input.environmentId,\n ...(input.variableName ? { name: input.variableName } : {}),\n },\n });\n}\n","import {\n CapabilityPack,\n type ScheduledTaskAgentConfig,\n type SocialConnection,\n} from \"@opengeni/contracts\";\nimport { getWorkspacePack, listPackInstallations, listWorkspacePacks, type Database } from \"@opengeni/db\";\nimport { HTTPException } from \"hono/http-exception\";\n\nexport const MARKETING_SOCIAL_PACK_ID = \"marketing-social-daily-analysis\";\n\nconst marketingSocialPack: CapabilityPack = {\n id: MARKETING_SOCIAL_PACK_ID,\n name: \"Marketing social daily analysis\",\n description: \"Connect social accounts, attach marketing knowledge, and schedule agents to produce daily media performance analysis.\",\n role: \"marketing\",\n category: \"social-media\",\n version: \"0.1.0\",\n // Built-in packs deliberately declare no sandboxImage and no skills: the\n // worker's pack-runtime resolution only reads manifest-registered packs\n // (see apps/worker/src/activities/packs.ts), and a test enforces this.\n skills: [],\n tools: [\n { kind: \"mcp\", id: \"opengeni\" },\n { kind: \"mcp\", id: \"docs\" },\n ],\n connectors: [\n {\n id: \"x\",\n name: \"X\",\n category: \"social-media\",\n authModel: \"oauth2_authorization_code_pkce\",\n providers: [\"x\"],\n scopes: [\"tweet.read\", \"users.read\", \"offline.access\"],\n required: false,\n metadata: {\n docs: \"https://docs.x.com/fundamentals/authentication/oauth-2-0/authorization-code\",\n },\n },\n {\n id: \"linkedin\",\n name: \"LinkedIn\",\n category: \"social-media\",\n authModel: \"oauth2_authorization_code\",\n providers: [\"linkedin\"],\n scopes: [\"r_organization_social\", \"rw_organization_admin\"],\n required: false,\n metadata: {\n docs: \"https://learn.microsoft.com/en-us/linkedin/marketing/community-management/community-management-overview\",\n },\n },\n {\n id: \"instagram\",\n name: \"Instagram\",\n category: \"social-media\",\n authModel: \"oauth2_authorization_code\",\n providers: [\"instagram\", \"facebook\"],\n scopes: [\"instagram_basic\", \"instagram_manage_insights\", \"pages_read_engagement\", \"pages_show_list\"],\n required: false,\n metadata: {\n docs: \"https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/\",\n },\n },\n {\n id: \"tiktok\",\n name: \"TikTok\",\n category: \"social-media\",\n authModel: \"oauth2_authorization_code\",\n providers: [\"tiktok\"],\n scopes: [\"user.info.basic\", \"video.list\"],\n required: false,\n metadata: {\n docs: \"https://developers.tiktok.com/doc/tiktok-api-v2-introduction/\",\n },\n },\n {\n id: \"youtube\",\n name: \"YouTube\",\n category: \"social-media\",\n authModel: \"oauth2_authorization_code\",\n providers: [\"youtube\"],\n scopes: [\"https://www.googleapis.com/auth/youtube.readonly\", \"https://www.googleapis.com/auth/yt-analytics.readonly\"],\n required: false,\n metadata: {\n docs: \"https://developers.google.com/youtube/v3\",\n },\n },\n ],\n knowledge: [\n {\n type: \"document_base\",\n id: \"marketing-playbook\",\n name: \"Marketing playbook\",\n description: \"Optional workspace document base with brand voice, campaign calendars, audience research, and reporting rules.\",\n required: false,\n },\n ],\n scheduledTaskTemplates: [\n {\n id: \"daily-social-analysis\",\n name: \"Daily social analysis\",\n description: \"Review the latest social posts and account signals every day.\",\n defaultSchedule: {\n type: \"calendar\",\n timeZone: \"UTC\",\n hour: 9,\n minute: 0,\n },\n defaultRunMode: \"new_session_per_run\",\n defaultOverlapPolicy: \"skip\",\n },\n ],\n metadata: {\n skill: \"social-media-marketing\",\n firstPartyMcpTools: [\n \"social_connections_list\",\n \"social_posts_recent\",\n \"social_daily_analysis_context\",\n ],\n },\n};\n\nconst packs = [marketingSocialPack] satisfies CapabilityPack[];\n\nexport function listCapabilityPacks(): CapabilityPack[] {\n return packs;\n}\n\nexport function getCapabilityPack(packId: string): CapabilityPack | null {\n return packs.find((pack) => pack.id === packId) ?? null;\n}\n\nexport function isBuiltInCapabilityPack(packId: string): boolean {\n return getCapabilityPack(packId) !== null;\n}\n\n/**\n * Built-in packs plus the manifests registered for this workspace. Stored\n * manifests were validated at registration time; rows that no longer parse\n * (for example after a contract tightening) are skipped instead of breaking\n * the whole catalog.\n */\nexport async function listWorkspaceCapabilityPacks(db: Database, workspaceId: string): Promise<CapabilityPack[]> {\n const registered = await listWorkspacePacks(db, workspaceId);\n const builtInIds = new Set(packs.map((pack) => pack.id));\n const registeredPacks = registered\n .filter((registration) => !builtInIds.has(registration.pack.id))\n .flatMap((registration) => {\n const parsed = CapabilityPack.safeParse(registration.pack);\n return parsed.success ? [parsed.data] : [];\n });\n return [...packs, ...registeredPacks];\n}\n\nexport async function resolveCapabilityPack(db: Database, workspaceId: string, packId: string): Promise<CapabilityPack | null> {\n const builtIn = getCapabilityPack(packId);\n if (builtIn) {\n return builtIn;\n }\n const registration = await getWorkspacePack(db, workspaceId, packId);\n if (!registration) {\n return null;\n }\n const parsed = CapabilityPack.safeParse(registration.pack);\n return parsed.success ? parsed.data : null;\n}\n\n/**\n * v1 pack-scoped runtime rule: at most one enabled pack per workspace may\n * declare a `sandboxImage` — there is deliberately no image composition or\n * layering. Enforced when a pack is enabled (both the packs endpoint and the\n * generic capability enable path) and re-checked at session start by the\n * worker, which also covers manifests re-registered after enablement.\n */\nexport async function assertPackSandboxImageCompatible(db: Database, workspaceId: string, pack: CapabilityPack): Promise<void> {\n if (!pack.sandboxImage) {\n return;\n }\n const installations = await listPackInstallations(db, workspaceId);\n for (const installation of installations) {\n if (installation.status !== \"active\" || installation.packId === pack.id) {\n continue;\n }\n const other = await resolveCapabilityPack(db, workspaceId, installation.packId);\n if (other?.sandboxImage) {\n throw new HTTPException(409, {\n message: `pack ${pack.id} declares a sandbox image, but enabled pack ${other.id} already declares one; only one enabled pack per workspace may declare sandboxImage — disable ${other.id} first`,\n });\n }\n }\n}\n\nexport function buildMarketingDailyAnalysisAgentConfig(input: {\n connections: SocialConnection[];\n documentBaseIds: string[];\n promptInstructions?: string;\n}): ScheduledTaskAgentConfig {\n const connectionIds = input.connections.map((connection) => connection.id);\n return {\n prompt: marketingDailyAnalysisPrompt({\n connections: input.connections,\n documentBaseIds: input.documentBaseIds,\n ...(input.promptInstructions ? { promptInstructions: input.promptInstructions } : {}),\n }),\n resources: [],\n tools: marketingSocialPack.tools,\n metadata: {\n packId: MARKETING_SOCIAL_PACK_ID,\n packTemplateId: \"daily-social-analysis\",\n socialConnectionIds: connectionIds,\n documentBaseIds: input.documentBaseIds,\n analysisWindowHours: 24,\n },\n };\n}\n\nfunction marketingDailyAnalysisPrompt(input: {\n connections: SocialConnection[];\n documentBaseIds: string[];\n promptInstructions?: string;\n}): string {\n const connectionLines = input.connections.map((connection) => {\n return `- ${connection.provider}: ${connection.accountHandle} (${connection.id})`;\n }).join(\"\\n\");\n const knowledgeLine = input.documentBaseIds.length > 0\n ? `Use these document base IDs for brand/campaign knowledge through the docs MCP: ${input.documentBaseIds.join(\", \")}.`\n : \"No document base IDs were selected; rely only on social context returned by tools.\";\n const extra = input.promptInstructions ? `\\nAdditional operator instructions:\\n${input.promptInstructions.trim()}\\n` : \"\";\n\n return [\n \"Run the daily social media analysis for the selected accounts.\",\n \"\",\n \"First call the OpenGeni MCP tool social_daily_analysis_context with the selected connection IDs and a 24 hour analysis window. Use social_posts_recent only if you need a narrower follow-up query.\",\n knowledgeLine,\n \"\",\n \"Selected accounts:\",\n connectionLines,\n extra,\n \"Produce a concise report with these sections: executive summary, notable account changes, winning posts, underperforming posts, audience and content signals, recommended actions for the next 24 hours, and data gaps.\",\n \"Use only metrics and posts returned by tools or document search. Do not invent metrics, posts, or account capabilities.\",\n ].filter(Boolean).join(\"\\n\");\n}\n","import type { Settings } from \"@opengeni/config\";\nimport {\n mergeResourceRefs as mergeContractResourceRefs,\n mergeToolRefs,\n resourceIdentityKey,\n ResourceRefConflictError,\n stableJson,\n type ResourceRef,\n type ToolRef,\n} from \"@opengeni/contracts\";\nimport {\n listGitHubInstallationIdsForWorkspace,\n requireFile,\n type Database,\n} from \"@opengeni/db\";\nimport { HTTPException } from \"hono/http-exception\";\n\nexport function validateToolRefs(tools: ToolRef[], settings: Settings): ToolRef[] {\n const mcpServerIds = new Set(settings.mcpServers.map((server) => server.id));\n const selected = new Set<string>();\n const out: ToolRef[] = [];\n for (const tool of tools) {\n if (tool.kind !== \"mcp\") {\n throw new HTTPException(422, { message: `unsupported tool kind: ${(tool as { kind?: string }).kind}` });\n }\n if (!mcpServerIds.has(tool.id)) {\n throw new HTTPException(422, { message: `unknown MCP server id: ${tool.id}` });\n }\n if (selected.has(tool.id)) {\n continue;\n }\n selected.add(tool.id);\n // Normalize to a bare, STRICT ref: a client-supplied `optional` flag is\n // dropped so an EXPLICITLY-requested tool always fails the turn when its\n // server is unavailable. `optional: true` is set only server-side, at the\n // default-capability auto-attach seam (enabledCapabilityMcpToolRefs).\n out.push({ kind: \"mcp\", id: tool.id });\n }\n return out;\n}\n\ntype McpSettings = Pick<Settings, \"mcpServers\">;\n\nexport function enabledCapabilityMcpToolRefs(settings: McpSettings, runtimeSettings: McpSettings): ToolRef[] {\n const configuredIds = new Set(settings.mcpServers.map((server) => server.id));\n return runtimeSettings.mcpServers\n .filter((server) => !configuredIds.has(server.id))\n // AUTO-ATTACHED (workspace-default) capability servers are marked optional:\n // one of them having a broken/expired credential must SKIP that server, not\n // fail the whole turn before the model runs. The caller only reaches here\n // when the request omitted `tools`; an explicit list is never defaulted.\n .map((server) => ({ kind: \"mcp\", id: server.id, optional: true }));\n}\n\nexport function withDefaultEnabledCapabilityMcpTools(tools: ToolRef[], settings: McpSettings, runtimeSettings: McpSettings): ToolRef[] {\n return mergeToolRefs(tools, enabledCapabilityMcpToolRefs(settings, runtimeSettings));\n}\n\nexport function normalizeResources(resources: ResourceRef[]): ResourceRef[] {\n const mountPaths = new Map<string, string>();\n const identities = new Map<string, string>();\n const seenResources = new Set<string>();\n const out: ResourceRef[] = [];\n for (const resource of resources) {\n let normalized: ResourceRef;\n if (resource.kind === \"file\") {\n const mountPath = normalizeMountPath(resource.mountPath ?? `files/${resource.fileId}`);\n normalized = {\n kind: \"file\",\n fileId: resource.fileId,\n mountPath,\n };\n } else {\n const url = parseResourceUrl(resource.uri);\n if (url.protocol !== \"https:\" || !url.hostname) {\n throw new HTTPException(422, { message: \"repository resources must use HTTPS Git URLs\" });\n }\n const path = url.pathname.replace(/^\\/+|\\/+$/g, \"\").replace(/\\.git$/, \"\");\n const parts = path.split(\"/\").filter(Boolean);\n if (parts.length < 2) {\n throw new HTTPException(422, { message: \"repository URL must include owner and repo\" });\n }\n const repo = parts.join(\"/\");\n const mountPath = normalizeMountPath(resource.mountPath ?? `repos/${repo}`);\n normalized = {\n kind: \"repository\",\n uri: `https://${url.hostname.toLowerCase()}/${repo}.git`,\n ref: resource.ref.trim(),\n mountPath,\n ...(resource.subpath ? { subpath: normalizeMountPath(resource.subpath) } : {}),\n ...(resource.githubInstallationId ? { githubInstallationId: resource.githubInstallationId } : {}),\n ...(resource.githubRepositoryId ? { githubRepositoryId: resource.githubRepositoryId } : {}),\n };\n }\n const key = stableJson(normalized);\n const mounted = normalized.mountPath ? mountPaths.get(normalized.mountPath) : undefined;\n if (mounted && mounted !== key) {\n throw new HTTPException(422, { message: `duplicate resource mount path: ${normalized.mountPath}` });\n }\n if (normalized.mountPath) {\n mountPaths.set(normalized.mountPath, key);\n }\n const identity = resourceIdentityKey(normalized);\n const seenIdentity = identities.get(identity);\n if (seenIdentity && seenIdentity !== key) {\n throw new HTTPException(422, { message: `duplicate resource with different settings: ${identity}` });\n }\n identities.set(identity, key);\n if (!seenResources.has(key)) {\n seenResources.add(key);\n out.push(normalized);\n }\n }\n return out;\n}\n\nexport function mergeResourceRefs(existing: ResourceRef[], additions: ResourceRef[]): ResourceRef[] {\n try {\n return mergeContractResourceRefs(existing, additions, { rejectConflicts: true });\n } catch (error) {\n if (error instanceof ResourceRefConflictError) {\n throw new HTTPException(422, { message: error.message });\n }\n throw error;\n }\n}\n\nexport function validateGitHubRepositorySelectionShape(resources: ResourceRef[]): number | null {\n const selected = resources.flatMap((resource) => {\n if (resource.kind !== \"repository\") {\n return [];\n }\n const installationRaw = resource.githubInstallationId;\n const repositoryRaw = resource.githubRepositoryId;\n if (installationRaw === null && repositoryRaw === null) {\n return [];\n }\n if (installationRaw === undefined && repositoryRaw === undefined) {\n return [];\n }\n const installationId = positiveInteger(installationRaw);\n const repositoryId = positiveInteger(repositoryRaw);\n if (!installationId || !repositoryId) {\n throw new HTTPException(422, {\n message: \"GitHub App repository resources require positive github_installation_id and github_repository_id\",\n });\n }\n return [{ installationId, repositoryId }];\n });\n if (selected.length === 0) {\n return null;\n }\n const installationId = selected[0]!.installationId;\n if (selected.some((item) => item.installationId !== installationId)) {\n throw new HTTPException(422, {\n message: \"GitHub App repository resources must belong to one installation\",\n });\n }\n return installationId;\n}\n\nexport async function validateGitHubRepositorySelection(db: Database, workspaceId: string, resources: ResourceRef[]): Promise<void> {\n const installationId = validateGitHubRepositorySelectionShape(resources);\n if (installationId === null) {\n return;\n }\n const linkedInstallationIds = new Set(await listGitHubInstallationIdsForWorkspace(db, workspaceId));\n if (!linkedInstallationIds.has(installationId)) {\n throw new HTTPException(422, {\n message: \"GitHub App repository resources must belong to a GitHub App installation linked to this workspace\",\n });\n }\n}\n\nexport async function validateFileResources(db: Database, workspaceId: string, resources: ResourceRef[]): Promise<void> {\n const fileIds = new Set<string>();\n for (const resource of resources) {\n if (resource.kind !== \"file\") {\n continue;\n }\n if (fileIds.has(resource.fileId)) {\n throw new HTTPException(422, { message: `duplicate file resource: ${resource.fileId}` });\n }\n fileIds.add(resource.fileId);\n const file = await requireFile(db, workspaceId, resource.fileId).catch(() => null);\n if (!file) {\n throw new HTTPException(422, { message: `unknown file resource: ${resource.fileId}` });\n }\n if (file.status !== \"ready\") {\n throw new HTTPException(422, { message: `file resource ${resource.fileId} is ${file.status}` });\n }\n }\n}\n\nfunction normalizeMountPath(path: string): string {\n const normalized = path.trim().replace(/^\\/+|\\/+$/g, \"\");\n if (!normalized || normalized.includes(\"..\")) {\n throw new HTTPException(422, { message: `invalid resource mount path: ${path}` });\n }\n return normalized;\n}\n\nfunction parseResourceUrl(uri: string): URL {\n try {\n return new URL(uri);\n } catch {\n throw new HTTPException(422, { message: \"repository resources must use valid URLs\" });\n }\n}\n\nfunction positiveInteger(value: unknown): number | null {\n if (typeof value === \"number\" && Number.isInteger(value) && value > 0) {\n return value;\n }\n if (typeof value === \"string\" && /^\\d+$/.test(value) && Number(value) > 0) {\n return Number(value);\n }\n return null;\n}\n\nexport { mergeToolRefs, stableJson };\n","import type { Settings } from \"@opengeni/config\";\nimport type {\n AccessGrant,\n ScheduledTask,\n ScheduledTaskAgentConfig,\n CreateScheduledTaskRequest as CreateScheduledTaskPayload,\n UpdateScheduledTaskRequest as UpdateScheduledTaskPayload,\n} from \"@opengeni/contracts\";\nimport {\n createScheduledTask,\n deleteScheduledTask,\n getScheduledTask,\n updateScheduledTask,\n type Database,\n type UpdateScheduledTaskInput,\n} from \"@opengeni/db\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { requirePermission } from \"../access\";\nimport type { SessionWorkflowClient } from \"../dependencies\";\nimport type { ObjectStorageDependency } from \"../dependencies\";\nimport { settingsWithEnabledCapabilityMcpServers } from \"./capabilities\";\nimport { validateEnvironmentAttachment } from \"./environments\";\nimport { assertConfiguredModel } from \"./sessions\";\nimport {\n normalizeResources,\n validateFileResources,\n validateGitHubRepositorySelection,\n validateToolRefs,\n withDefaultEnabledCapabilityMcpTools,\n} from \"./resources\";\n\n/**\n * Whether a raw scheduled-task payload explicitly set agentConfig.tools.\n * Zod's `.default([])` erases the distinction between \"absent\" and\n * \"explicitly empty\", so callers detect it on the raw payload — the same\n * contract sessions use: absent tools mean \"give me the workspace defaults\n * (enabled capability MCP servers)\", an explicit list (even empty) is taken\n * verbatim.\n */\nexport function scheduledTaskToolsProvided(rawPayload: unknown): boolean {\n if (!rawPayload || typeof rawPayload !== \"object\") {\n return false;\n }\n const agentConfig = (rawPayload as { agentConfig?: unknown }).agentConfig;\n return Boolean(\n agentConfig\n && typeof agentConfig === \"object\"\n && Object.prototype.hasOwnProperty.call(agentConfig, \"tools\"),\n );\n}\n\nexport async function createValidatedScheduledTask(input: {\n settings: Settings;\n db: Database;\n objectStorage: ObjectStorageDependency;\n grant: AccessGrant;\n payload: CreateScheduledTaskPayload;\n // Whether the caller explicitly set agentConfig.tools (see\n // scheduledTaskToolsProvided). Absent tools get the workspace's enabled\n // capability MCP servers, mirroring session creation.\n toolsProvided?: boolean;\n // Set for pack-installation-inherited attachments that were already\n // authorized with environments:use when the pack was enabled.\n environmentPreauthorized?: boolean;\n}): Promise<ScheduledTask> {\n const agentConfig = await validateScheduledTaskAgentConfig({ ...input, workspaceId: input.grant.workspaceId });\n const id = crypto.randomUUID();\n validateScheduledTaskSchedule(input.payload.schedule);\n if (input.payload.environmentId) {\n await validateEnvironmentAttachment(\n { settings: input.settings, db: input.db },\n input.grant,\n input.grant.workspaceId,\n input.payload.environmentId,\n { preauthorized: input.environmentPreauthorized ?? false },\n );\n }\n return await createScheduledTask(input.db, {\n id,\n accountId: input.grant.accountId,\n workspaceId: input.grant.workspaceId,\n name: trimmedScheduledTaskName(input.payload.name),\n status: input.payload.status,\n schedule: input.payload.schedule,\n temporalScheduleId: scheduledTaskTemporalScheduleId(id),\n runMode: input.payload.runMode,\n overlapPolicy: input.payload.overlapPolicy,\n agentConfig,\n environmentId: input.payload.environmentId ?? null,\n metadata: input.payload.metadata,\n });\n}\n\nexport async function validatedScheduledTaskUpdate(input: {\n settings: Settings;\n db: Database;\n objectStorage: ObjectStorageDependency;\n grant: AccessGrant;\n existing: ScheduledTask;\n payload: UpdateScheduledTaskPayload;\n /** See createValidatedScheduledTask; only consulted when agentConfig is updated. */\n toolsProvided?: boolean;\n}): Promise<UpdateScheduledTaskInput> {\n const update: UpdateScheduledTaskInput = {};\n if (input.payload.name !== undefined) {\n update.name = trimmedScheduledTaskName(input.payload.name);\n }\n if (input.payload.status !== undefined) {\n update.status = input.payload.status;\n }\n if (input.payload.schedule !== undefined) {\n validateScheduledTaskSchedule(input.payload.schedule);\n update.schedule = input.payload.schedule;\n }\n if (input.payload.runMode !== undefined) {\n update.runMode = input.payload.runMode;\n }\n if (input.payload.overlapPolicy !== undefined) {\n update.overlapPolicy = input.payload.overlapPolicy;\n }\n if (input.payload.metadata !== undefined) {\n update.metadata = input.payload.metadata;\n }\n if (input.payload.environmentId !== undefined) {\n const nextEnvironmentId = input.payload.environmentId;\n if ((input.existing.environmentId ?? null) !== (nextEnvironmentId ?? null)\n && input.existing.runMode === \"reusable_session\"\n && input.existing.reusableSessionId) {\n throw new HTTPException(409, { message: \"cannot change environment of a task with a live reusable session; recreate the task\" });\n }\n if (nextEnvironmentId === null) {\n if (input.existing.environmentId !== null) {\n // Detaching is also an attachment change: it strips the secrets a\n // task's instructions were designed around.\n requirePermission(input.grant, \"environments:use\");\n }\n update.environmentId = null;\n } else {\n await validateEnvironmentAttachment(\n { settings: input.settings, db: input.db },\n input.grant,\n input.existing.workspaceId,\n nextEnvironmentId,\n );\n update.environmentId = nextEnvironmentId;\n }\n }\n if (input.payload.agentConfig !== undefined) {\n // Editing the instructions of a task that injects workspace secrets is\n // equivalent to attaching those secrets to new instructions, so it\n // requires environments:use even though plain task edits do not.\n const willHaveEnvironment = input.payload.environmentId !== undefined\n ? input.payload.environmentId !== null\n : Boolean(input.existing.environmentId);\n if (willHaveEnvironment) {\n requirePermission(input.grant, \"environments:use\");\n }\n update.agentConfig = await validateScheduledTaskAgentConfig({\n settings: input.settings,\n db: input.db,\n objectStorage: input.objectStorage,\n workspaceId: input.existing.workspaceId,\n payload: { agentConfig: input.payload.agentConfig },\n ...(input.toolsProvided !== undefined ? { toolsProvided: input.toolsProvided } : {}),\n });\n }\n return update;\n}\n\nexport async function requireScheduledTaskForApi(db: Database, workspaceId: string, taskId: string): Promise<ScheduledTask> {\n const task = await getScheduledTask(db, workspaceId, taskId);\n if (!task) {\n throw new HTTPException(404, { message: \"scheduled task not found\" });\n }\n return task;\n}\n\nexport async function restoreScheduledTask(db: Database, task: ScheduledTask): Promise<ScheduledTask> {\n return await updateScheduledTask(db, task.workspaceId, task.id, {\n name: task.name,\n status: task.status,\n schedule: task.schedule,\n runMode: task.runMode,\n overlapPolicy: task.overlapPolicy,\n agentConfig: task.agentConfig,\n reusableSessionId: task.reusableSessionId,\n environmentId: task.environmentId,\n metadata: task.metadata,\n });\n}\n\nexport async function syncCreatedScheduledTask(input: {\n db: Database;\n workflowClient: SessionWorkflowClient;\n task: ScheduledTask;\n}): Promise<void> {\n try {\n await input.workflowClient.syncScheduledTask({ task: input.task });\n } catch (error) {\n await deleteScheduledTask(input.db, input.task.workspaceId, input.task.id).catch(() => undefined);\n throw error;\n }\n}\n\nexport async function syncUpdatedScheduledTask(input: {\n db: Database;\n workflowClient: SessionWorkflowClient;\n previous: ScheduledTask;\n task: ScheduledTask;\n}): Promise<void> {\n try {\n await input.workflowClient.syncScheduledTask({ task: input.task });\n } catch (error) {\n await restoreScheduledTask(input.db, input.previous).catch(() => undefined);\n throw error;\n }\n}\n\nexport function scheduledTaskTemporalScheduleId(taskId: string): string {\n return `scheduled-task-${taskId}`;\n}\n\n/**\n * Stable token that identifies a single logical manual trigger. A client that\n * retries a `/trigger` POST (network blip, lambda re-invocation) passes the\n * SAME token so the retry is idempotent — one usage charge, one workflow run.\n * When the client supplies nothing we mint one UUID PER REQUEST and reuse it\n * for both the idempotency key and the workflowId, so a single request stays\n * internally consistent while two genuinely-distinct manual triggers (no token,\n * fired a second apart) still each get their own run. The token is sanitized to\n * the Temporal workflow-id-safe charset so a client value cannot smuggle a\n * collision into a different task's id space.\n */\nexport function scheduledTaskTriggerToken(clientTriggerId?: string | null): string {\n const trimmed = (clientTriggerId ?? \"\").trim();\n if (!trimmed) {\n return crypto.randomUUID();\n }\n const safe = trimmed.replace(/[^a-zA-Z0-9._-]/g, \"_\").slice(0, 128);\n // A value that sanitizes to empty (only disallowed chars) is unusable as a\n // stable id; fall back to a fresh token rather than collapse to a constant.\n return safe.length > 0 ? safe : crypto.randomUUID();\n}\n\n/**\n * Deterministic Temporal workflow id for a manual trigger. Derived purely from\n * the task id and the stable trigger token, so a retry with the same token maps\n * to the same id and `workflowIdReusePolicy: \"REJECT_DUPLICATE\"` collapses the\n * second start into a no-op instead of spawning a second run.\n */\nexport function manualScheduledTaskTriggerWorkflowId(taskId: string, triggerToken: string): string {\n return `scheduled-task-${taskId}-manual-${triggerToken}`;\n}\n\n/**\n * Deterministic usage idempotency key for a manual trigger's agent_run.created\n * charge. Shares the stable trigger token with the workflow id so the charge\n * and the run dedupe together under retry.\n */\nexport function manualScheduledTaskTriggerUsageKey(workspaceId: string, taskId: string, triggerToken: string): string {\n return `agent_run.created:scheduled-trigger:${workspaceId}:${taskId}:${triggerToken}`;\n}\n\nasync function validateScheduledTaskAgentConfig(input: {\n settings: Settings;\n db: Database;\n objectStorage: ObjectStorageDependency;\n payload: { agentConfig: ScheduledTaskAgentConfig };\n workspaceId: string;\n toolsProvided?: boolean;\n}): Promise<ScheduledTaskAgentConfig> {\n // Reject a curated-out model before touching the DB: a scheduled task is a\n // session the worker runs later, so it must pass the same allow-list as the\n // session choke points (a `scheduled_tasks:manage` holder could otherwise set\n // a model the host does not expose). An omitted model inherits the host\n // default downstream, which is always configured.\n assertConfiguredModel(input.settings, input.payload.agentConfig.model);\n const resources = normalizeResources(input.payload.agentConfig.resources ?? []);\n const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(input.db, input.workspaceId, input.settings);\n const requestedTools = validateToolRefs(input.payload.agentConfig.tools ?? [], runtimeSettings);\n // A task whose creator did not choose tools gets the workspace's enabled\n // capability MCP servers, exactly like a session created without a tools\n // key. Scheduled runs are sessions too; \"no MCP servers at all\" was a trap\n // every pack/template instantiation path kept falling into (a maintenance\n // task that cannot reach its workspace's notebook MCP cannot do its job).\n const tools = (input.toolsProvided ?? true)\n ? requestedTools\n : withDefaultEnabledCapabilityMcpTools(requestedTools, input.settings, runtimeSettings);\n const prompt = input.payload.agentConfig.prompt.trim();\n if (!prompt) {\n throw new HTTPException(422, { message: \"scheduled task prompt is required\" });\n }\n await validateGitHubRepositorySelection(input.db, input.workspaceId, resources);\n if (resources.some((resource) => resource.kind === \"file\") && !input.objectStorage) {\n throw new HTTPException(503, { message: \"object storage is not configured\" });\n }\n await validateFileResources(input.db, input.workspaceId, resources);\n return {\n ...input.payload.agentConfig,\n prompt,\n resources,\n tools,\n };\n}\n\nfunction validateScheduledTaskSchedule(schedule: ScheduledTask[\"schedule\"]): void {\n if (schedule.type !== \"interval\" || !schedule.startAt || !schedule.endAt) {\n return;\n }\n if (new Date(schedule.startAt).getTime() >= new Date(schedule.endAt).getTime()) {\n throw new HTTPException(422, { message: \"interval schedule endAt must be after startAt\" });\n }\n}\n\nfunction trimmedScheduledTaskName(name: string): string {\n const trimmed = name.trim();\n if (!trimmed) {\n throw new HTTPException(422, { message: \"scheduled task name is required\" });\n }\n return trimmed;\n}\n","import { CODEX_MODEL_ID_PREFIX } from \"@opengeni/codex\";\nimport { configuredAllowedModels, type Settings } from \"@opengeni/config\";\nimport {\n CreateSessionRequest,\n reasoningEffortForMetadata,\n type AccessGrant,\n type GoalSpec,\n type Permission,\n type ReasoningEffort,\n type ResourceRef,\n type Session,\n type SessionEvent,\n type SessionTurn,\n type ToolRef,\n} from \"@opengeni/contracts\";\nimport {\n appendSessionEventsWithLockedSessionUpdate,\n createSession,\n createSessionGoal,\n createSessionWithIdempotencyKey,\n enqueueSessionTurn,\n getAnySessionInGroup,\n getEnrollment,\n listDistinctEnvironmentIdsInGroup,\n getSandbox,\n getSession,\n getSessionByCreateIdempotencyKey,\n getSessionTurn,\n requireSession,\n setTemporalWorkflowId,\n updateSessionTitle as updateSessionTitleRow,\n type Database,\n} from \"@opengeni/db\";\nimport { appendAndPublishEvents, type EventBus } from \"@opengeni/events\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { hasPermission } from \"../access\";\nimport { recordWorkspaceUsage, requireLimit } from \"../billing/limits\";\nimport type { ApiRouteDeps, SessionWorkflowClient } from \"../dependencies\";\nimport { swapActiveSandbox, type FleetContext } from \"../sandbox/fleet\";\nimport { settingsWithEnabledCapabilityMcpServers } from \"./capabilities\";\nimport { validateEnvironmentAttachment } from \"./environments\";\nimport {\n mergeResourceRefs,\n mergeToolRefs,\n normalizeResources,\n validateFileResources,\n validateGitHubRepositorySelection,\n validateToolRefs,\n withDefaultEnabledCapabilityMcpTools,\n} from \"./resources\";\n\nexport async function createAndStartSession(input: {\n db: Database;\n bus: EventBus;\n workflowClient: SessionWorkflowClient;\n accountId: string;\n workspaceId: string;\n initialMessage: string;\n resources: ResourceRef[];\n tools: ToolRef[];\n clientEventId?: string;\n model: string;\n reasoningEffort: Settings[\"openaiReasoningEffort\"];\n sandboxBackend: Settings[\"sandboxBackend\"];\n metadata: Record<string, unknown>;\n // Names/ids only; the session.created payload never carries variable values.\n environment?: { id: string; name: string } | null;\n goal?: GoalSpec | null;\n // Validated against the creating grant before this is called.\n firstPartyMcpPermissions?: Permission[] | null;\n // The manager session spawning this worker (a worker-signed sessionId claim\n // on the creating grant); null for direct API creates and scheduled runs.\n // When set, the worker's terminal-for-now transitions wake this parent.\n parentSessionId?: string | null;\n // Workspace-scoped CREATE idempotency key. When present, a double-fire with\n // the same key (sequential retry OR concurrent race) collapses to a single\n // session: a prior winner is returned as-is and the start flow below is\n // skipped, so the dup never re-emits events / re-enqueues a turn.\n createIdempotencyKey?: string | null;\n // The shared-sandbox group this session's box joins (addendum 05 §D). Null/\n // omitted ⇒ a singleton group (the new row's own id, today's 1:1 behavior); a\n // shared/{groupId} spawn passes the resolved group so both run in ONE box.\n sandboxGroupId?: string | null;\n // The OS axis of the session's box (sessions.sandbox_os). Omitted ⇒ the\n // \"linux\" default; set only for a machine-targeted top-level create, where the\n // targeted machine's enrollment OS is threaded in so the row + resume path +\n // OS-labeling surfaces honestly reflect the machine.\n sandboxOs?: Session[\"sandboxOs\"];\n // Create-time machine targeting (A-2a, RACE-FREE): the enrolled machine (a\n // sandbox id) to run this session on. When set, the active-sandbox pointer is\n // resolved+validated+seeded (epoch-fenced) INSIDE finishStartSession, AFTER the\n // session row exists but BEFORE the first turn is enqueued/the workflow woken,\n // so the FIRST turn routes to the chosen machine. An invalid/unowned/offline\n // target fails the create (422) — never a silent fall-back to the default box.\n // `workingDir` (optional) is the path/cwd base the chosen machine runs under,\n // seeded alongside the pointer through the epoch-fenced CAS.\n seedTargetSandbox?: { sandboxId: string; settings: Settings; workingDir?: string | null } | null;\n}) {\n const sessionMetadata = {\n ...input.metadata,\n model: input.model,\n reasoningEffort: input.reasoningEffort,\n };\n // Fast path with a key: return a session already created under this key\n // (the sequential retry / double-submit case) without inserting again.\n if (input.createIdempotencyKey) {\n const existing = await getSessionByCreateIdempotencyKey(input.db, input.workspaceId, input.createIdempotencyKey);\n if (existing) {\n return existing;\n }\n // No prior session: insert under the key, racing concurrent creates. The\n // partial unique index lets exactly one insert win; a loser gets back the\n // winner's row with created=false and must NOT run the start flow (the\n // winner owns the events/turn/workflow), so we return it as-is.\n const { session: keyed, created } = await createSessionWithIdempotencyKey(input.db, {\n accountId: input.accountId,\n workspaceId: input.workspaceId,\n initialMessage: input.initialMessage,\n resources: input.resources,\n tools: input.tools,\n metadata: sessionMetadata,\n model: input.model,\n sandboxBackend: input.sandboxBackend,\n environmentId: input.environment?.id ?? null,\n firstPartyMcpPermissions: input.firstPartyMcpPermissions ?? null,\n parentSessionId: input.parentSessionId ?? null,\n createIdempotencyKey: input.createIdempotencyKey,\n sandboxGroupId: input.sandboxGroupId ?? null,\n ...(input.sandboxOs ? { sandboxOs: input.sandboxOs } : {}),\n });\n if (!created) {\n return keyed;\n }\n return await finishStartSession(input, keyed);\n }\n const session = await createSession(input.db, {\n accountId: input.accountId,\n workspaceId: input.workspaceId,\n initialMessage: input.initialMessage,\n resources: input.resources,\n tools: input.tools,\n metadata: sessionMetadata,\n model: input.model,\n sandboxBackend: input.sandboxBackend,\n environmentId: input.environment?.id ?? null,\n firstPartyMcpPermissions: input.firstPartyMcpPermissions ?? null,\n parentSessionId: input.parentSessionId ?? null,\n sandboxGroupId: input.sandboxGroupId ?? null,\n ...(input.sandboxOs ? { sandboxOs: input.sandboxOs } : {}),\n });\n return await finishStartSession(input, session);\n}\n\n/**\n * The post-insert half of {@link createAndStartSession}: durable goal row,\n * the initial event batch (session.created / goal.set / user.message /\n * status.changed), turn enqueue, and the workflow wake. Split out so the\n * idempotency-key winner and the key-less create share one body, and the\n * idempotency-key loser/dup can skip it entirely.\n */\nasync function finishStartSession(input: {\n db: Database;\n bus: EventBus;\n workflowClient: SessionWorkflowClient;\n initialMessage: string;\n resources: ResourceRef[];\n tools: ToolRef[];\n clientEventId?: string;\n model: string;\n reasoningEffort: Settings[\"openaiReasoningEffort\"];\n sandboxBackend: Settings[\"sandboxBackend\"];\n environment?: { id: string; name: string } | null;\n goal?: GoalSpec | null;\n seedTargetSandbox?: { sandboxId: string; settings: Settings; workingDir?: string | null } | null;\n}, session: Session): Promise<Session> {\n // The goal row is durable session state; the workflow picks it up from the\n // database once the first turn completes — no extra workflow plumbing here.\n const goal = input.goal\n ? await createSessionGoal(input.db, {\n accountId: session.accountId,\n workspaceId: session.workspaceId,\n sessionId: session.id,\n text: input.goal.text,\n successCriteria: input.goal.successCriteria ?? null,\n maxAutoContinuations: input.goal.maxAutoContinuations ?? null,\n createdBy: \"api\",\n })\n : null;\n const initialPayload = {\n text: input.initialMessage,\n ...(input.resources.length ? { resources: input.resources } : {}),\n ...(input.tools.length ? { tools: input.tools } : {}),\n };\n const events = await appendAndPublishEvents(input.db, input.bus, session.workspaceId, session.id, [\n {\n type: \"session.created\",\n payload: {\n status: \"queued\",\n ...(input.environment ? { environmentId: input.environment.id, environmentName: input.environment.name } : {}),\n },\n },\n ...(goal ? [{\n type: \"goal.set\" as const,\n payload: {\n goalId: goal.id,\n text: goal.text,\n ...(goal.successCriteria ? { successCriteria: goal.successCriteria } : {}),\n version: goal.version,\n actor: \"api\",\n replaced: false,\n },\n }] : []),\n {\n type: \"user.message\",\n payload: initialPayload,\n ...(input.clientEventId ? { clientEventId: input.clientEventId } : {}),\n },\n { type: \"session.status.changed\", payload: { status: \"queued\" } },\n ]);\n const userEvent = events.find((event) => event.type === \"user.message\");\n if (!userEvent) {\n throw new HTTPException(500, { message: \"failed to append initial user event\" });\n }\n // Create-time machine targeting (A-2a): seed the active-sandbox pointer BEFORE\n // the first turn is enqueued + the workflow woken, so the FIRST turn routes to\n // the chosen machine. Race-free: the epoch-fenced setActiveSandbox commits here,\n // before wakeSessionWorkflow below signals the worker. swapActiveSandbox does\n // the same ownership+liveness validation as the live swap; an invalid/unowned/\n // offline target FAILS the create (422) — never a silent fall-back to the box.\n if (input.seedTargetSandbox) {\n if (session.sandboxBackend === \"none\") {\n throw new HTTPException(422, {\n message: \"cannot target a machine for a session with no sandbox (backend: none)\",\n });\n }\n const ctx: FleetContext = {\n accountId: session.accountId,\n workspaceId: session.workspaceId,\n sessionId: session.id,\n sessionBackend: session.sandboxBackend,\n sessionGroupId: session.sandboxGroupId,\n };\n const seeded = await swapActiveSandbox(\n { db: input.db, settings: input.seedTargetSandbox.settings, bus: input.bus },\n ctx,\n input.seedTargetSandbox.sandboxId,\n // The working dir is committed in the SAME epoch-fenced CAS that seeds the\n // pointer, so the first turn routes to the machine AND lands in working_dir.\n input.seedTargetSandbox.workingDir ?? null,\n );\n if (!seeded.swapped) {\n throw new HTTPException(422, {\n message: `cannot target sandbox ${input.seedTargetSandbox.sandboxId}: ${seeded.reason ?? \"target is not attachable\"}`,\n });\n }\n }\n const workflowId = workflowIdForSession(session.id);\n await setTemporalWorkflowId(input.db, session.workspaceId, session.id, workflowId);\n const turn = await enqueueSessionTurn(input.db, {\n accountId: session.accountId,\n workspaceId: session.workspaceId,\n sessionId: session.id,\n triggerEventId: userEvent.id,\n temporalWorkflowId: workflowId,\n source: \"user\",\n prompt: input.initialMessage,\n resources: input.resources,\n tools: input.tools,\n model: input.model,\n reasoningEffort: input.reasoningEffort,\n sandboxBackend: input.sandboxBackend,\n metadata: {},\n });\n await appendAndPublishEvents(input.db, input.bus, session.workspaceId, session.id, [{\n type: \"turn.queued\",\n turnId: turn.id,\n payload: { turnId: turn.id, triggerEventId: userEvent.id, source: turn.source },\n }]);\n await input.workflowClient.wakeSessionWorkflow({ accountId: session.accountId, workspaceId: session.workspaceId, sessionId: session.id, workflowId });\n return await requireSession(input.db, session.workspaceId, session.id);\n}\n\nexport function workflowIdForSession(sessionId: string): string {\n return `session-${sessionId}`;\n}\n\n/**\n * Reject an explicit model that the host does not expose. The set of usable\n * models is the union surfaced by `configuredAllowedModels` (the built-in\n * provider's allow-list plus every registry provider's ids); a `model` outside\n * it cannot be resolved to a provider at run time, so we fail the request at\n * the API edge with 422 rather than enqueuing a turn the worker can't honor.\n *\n * `model` is the explicit, caller-supplied value (null/undefined when omitted).\n * An omitted model defaults to `settings.openaiModel` downstream — which is\n * always first in `configuredAllowedModels` — so only an explicit value is\n * checked. Centralized here so every model-carrying choke point\n * (create-session, user-message/turn-accept, queued-turn update, and\n * scheduled-task agentConfig — a scheduled task is a session the worker runs\n * later) and the MCP surfaces that share them validate identically and cannot\n * drift.\n */\nexport function assertConfiguredModel(settings: Settings, model: string | null | undefined): void {\n if (model === null || model === undefined) {\n return;\n }\n if (configuredAllowedModels(settings).includes(model)) {\n return;\n }\n // Codex subscription models (codex/<slug>) are injected per-workspace by the\n // worker overlay at turn time, so they are never in the deployment-global\n // allow-list. Accept them at the edge when the feature is enabled — the picker\n // only surfaces them for a connected workspace, and the worker enforces the\n // actual connection (an unconnected workspace fails the turn with a clear\n // \"no Codex subscription connected\" error rather than a misleading 422 here).\n if (settings.codexSubscriptionEnabled && model.startsWith(CODEX_MODEL_ID_PREFIX)) {\n return;\n }\n throw new HTTPException(422, { message: `model is not available: ${model}` });\n}\n\nexport async function requireQueuedTurnForApi(db: Database, workspaceId: string, sessionId: string, turnId: string): Promise<SessionTurn> {\n const turn = await getSessionTurn(db, workspaceId, turnId);\n if (!turn || turn.sessionId !== sessionId) {\n throw new HTTPException(404, { message: \"session turn not found\" });\n }\n if (turn.status !== \"queued\") {\n throw new HTTPException(409, { message: `turn is ${turn.status}; only queued turns can be changed` });\n }\n return turn;\n}\n\nexport function reasoningEffortForSession(metadata: Record<string, unknown>, fallback: Settings[\"openaiReasoningEffort\"]): Settings[\"openaiReasoningEffort\"] {\n return reasoningEffortForMetadata(metadata, fallback);\n}\n\n/**\n * Appends a `user.message` to an existing session and enqueues the resulting\n * turn, merging requested resources/tools into the session and waking the\n * workflow. Shared by the public events route and the first-party MCP\n * `session_send_message` tool so the two surfaces cannot drift. Callers own\n * resource/tool validation and the per-message usage limit before calling.\n */\nexport async function postUserMessageTurn(input: {\n db: Database;\n bus: EventBus;\n workflowClient: SessionWorkflowClient;\n settings: Settings;\n accountId: string;\n workspaceId: string;\n sessionId: string;\n text: string;\n resources: ResourceRef[];\n tools: ToolRef[];\n model?: string | null;\n reasoningEffort?: Settings[\"openaiReasoningEffort\"] | null;\n clientEventId?: string;\n}): Promise<{ accepted: SessionEvent; turn: SessionTurn }> {\n const { db, bus, workflowClient, settings, accountId, workspaceId, sessionId } = input;\n const requestedModel = input.model ?? null;\n const requestedReasoningEffort = input.reasoningEffort ?? null;\n // Reject an explicit per-message model the host does not expose; an omitted\n // model inherits the session's model downstream (always a configured id).\n assertConfiguredModel(settings, requestedModel);\n const appended = await appendSessionEventsWithLockedSessionUpdate(db, workspaceId, sessionId, (lockedSession) => {\n // Cancelled is the one terminal state: an explicit user act. A FAILED\n // session stays revivable by talking to it — conversation truth lives in\n // session_history_items, so a failed turn does not invalidate history,\n // and the manager channel of record must always answer when spoken to.\n // The new message transitions failed -> queued (clearing the stale\n // activeTurnId) and the signalWithStart below starts a fresh workflow\n // run for the completed (failed) one, exactly as for idle sessions.\n if (lockedSession.status === \"cancelled\") {\n throw new HTTPException(409, { message: `session is ${lockedSession.status}; cannot accept a new user message` });\n }\n const nextResources = mergeResourceRefs(lockedSession.resources, input.resources);\n const nextTools = mergeToolRefs(lockedSession.tools, input.tools);\n const shouldQueueSession = lockedSession.status === \"idle\" || lockedSession.status === \"failed\";\n return {\n events: [\n {\n type: \"user.message\",\n payload: {\n text: input.text,\n ...(input.resources.length ? { resources: input.resources } : {}),\n ...(input.tools.length ? { tools: input.tools } : {}),\n ...(requestedModel ? { model: requestedModel } : {}),\n ...(requestedReasoningEffort ? { reasoningEffort: requestedReasoningEffort } : {}),\n },\n ...(input.clientEventId ? { clientEventId: input.clientEventId } : {}),\n },\n ...(shouldQueueSession ? [{ type: \"session.status.changed\" as const, payload: { status: \"queued\" } }] : []),\n ],\n update: {\n resources: nextResources,\n tools: nextTools,\n ...(shouldQueueSession ? { status: \"queued\" as const, activeTurnId: null } : {}),\n },\n };\n }).then(async (events) => {\n await bus.publish(workspaceId, sessionId, events);\n return events;\n });\n const accepted = appended[0];\n if (!accepted) {\n throw new HTTPException(500, { message: \"failed to append client event\" });\n }\n const workflowId = workflowIdForSession(sessionId);\n const session = await requireSession(db, workspaceId, sessionId);\n const turn = await enqueueSessionTurn(db, {\n accountId,\n workspaceId,\n sessionId,\n triggerEventId: accepted.id,\n temporalWorkflowId: workflowId,\n source: \"user\",\n prompt: input.text,\n resources: input.resources,\n tools: input.tools,\n model: requestedModel ?? session.model,\n reasoningEffort: requestedReasoningEffort ?? reasoningEffortForSession(session.metadata, settings.openaiReasoningEffort),\n sandboxBackend: session.sandboxBackend,\n metadata: {},\n });\n await appendAndPublishEvents(db, bus, workspaceId, sessionId, [{\n type: \"turn.queued\",\n turnId: turn.id,\n payload: { turnId: turn.id, triggerEventId: accepted.id, source: turn.source },\n }]);\n await workflowClient.wakeSessionWorkflow({ accountId, workspaceId, sessionId, workflowId });\n return { accepted, turn };\n}\n\n/**\n * Full create-session flow shared by `POST /sessions` and the first-party MCP\n * `session_create` tool: payload validation, resource/tool/environment\n * checks, usage limits, session start, and usage recording. `rawPayload` is\n * the unparsed request body so absent-vs-empty `tools` keeps its meaning\n * (absent applies the workspace's default capability MCP tools).\n */\nexport async function createSessionForRequest(\n deps: ApiRouteDeps,\n grant: AccessGrant,\n workspaceId: string,\n rawPayload: unknown,\n): Promise<Session> {\n const { settings, db, bus, workflowClient, objectStorage } = deps;\n const payload = CreateSessionRequest.parse(rawPayload);\n const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings);\n const resources = normalizeResources(payload.resources);\n const requestedTools = validateToolRefs(payload.tools, runtimeSettings);\n const defaultedTools = hasOwnProperty(rawPayload, \"tools\")\n ? requestedTools\n : withDefaultEnabledCapabilityMcpTools(requestedTools, settings, runtimeSettings);\n // The first-party MCP server is attached to EVERY session. It hosts the\n // session's own metadata tool (set_session_title) + goal tools, and — only\n // when the grant carries the permission — the orchestration/environment/\n // github tools. Capability is gated per-tool by permission, never by whether\n // the server is attached, so a bare chat still gets titling while the\n // dangerous tools stay off by default.\n const tools = withFirstPartyTools(defaultedTools, runtimeSettings);\n await validateGitHubRepositorySelection(db, workspaceId, resources);\n if (resources.some((resource) => resource.kind === \"file\") && !objectStorage) {\n throw new HTTPException(503, { message: \"object storage is not configured\" });\n }\n await validateFileResources(db, workspaceId, resources);\n // Environment attachment requires environments:use on the calling grant\n // (validateEnvironmentAttachment enforces it), preserving the invariant\n // that sandboxed agents cannot self-attach workspace secrets.\n const environment = payload.environmentId\n ? await validateEnvironmentAttachment({ settings, db }, grant, workspaceId, payload.environmentId)\n : null;\n assertConfiguredModel(settings, payload.model);\n const model = payload.model ?? settings.openaiModel;\n const reasoningEffort = payload.reasoningEffort ?? settings.openaiReasoningEffort;\n // A session's first-party MCP token can carry a non-default permission set\n // (how an operator hands a manager-style session the orchestration tools),\n // but never one out-ranking its creator: every requested permission must be\n // held by the creating grant.\n let firstPartyMcpPermissions = payload.firstPartyMcpPermissions ?? null;\n if (firstPartyMcpPermissions && firstPartyMcpPermissions.length === 0) {\n // An empty set would sign an unusable zero-permission token; the default\n // worker set is expressed by omitting the field.\n throw new HTTPException(422, { message: \"firstPartyMcpPermissions must not be empty; omit it for the default worker permission set\" });\n }\n for (const permission of firstPartyMcpPermissions ?? []) {\n if (!hasPermission(grant.permissions, permission)) {\n throw new HTTPException(403, { message: `cannot grant first-party MCP permission beyond the creating grant: ${permission}` });\n }\n }\n // Invariant: a goal-bearing session always carries goals:manage in its\n // effective first-party permissions. Without it the worker's delegated\n // token never sees the goal tools (goal_complete/goal_pause/...), so the\n // agent cannot stop its own goal and the continuation loop runs until an\n // operator intervenes. The auto-added permission is deliberately exempt\n // from the creating-grant check above: goal tools are scoped to the\n // spawned session itself via the worker-signed sessionId claim, so a\n // worker managing its OWN goal is not an escalation of the spawner's\n // authority.\n if (payload.goal && firstPartyMcpPermissions && !firstPartyMcpPermissions.includes(\"goals:manage\")) {\n firstPartyMcpPermissions = [...firstPartyMcpPermissions, \"goals:manage\"];\n }\n // Parent linkage: a worker is linked to its manager ONLY from the\n // worker-signed sessionId claim on the creating grant — the manager\n // session's own id, signed into the delegated token by the worker and never\n // agent- or caller-controlled. A grant without that claim (a workspace API\n // key, any non-delegated grant) creates a parentless top-level session.\n //\n // We deliberately do NOT honor a caller-supplied parentSessionId: it would\n // let any sessions:create grant aim a worker at an arbitrary session's id so\n // its completion wake injects a user.message + queued turn into that session\n // without holding sessions:control on it (a cross-session write escalation).\n // The claim is the only trustworthy parent source.\n const parentSessionId = typeof grant.metadata?.[\"sessionId\"] === \"string\" ? grant.metadata[\"sessionId\"] as string : null;\n // Shared-sandbox placement (addendum 05 §D.2/§D.3, decision I10/OD-S1).\n //\n // The DEFAULT rule is context-dependent and resolved server-side from the\n // TRUSTED claim, never caller-supplied: when `sandbox` is omitted, a session\n // spawned FROM INSIDE a session (parentSessionId present ⇒ a worker-signed\n // sessionId claim) defaults to \"shared\" (join the creator's box); a top-level\n // create (no parent) defaults to \"new\" (a private singleton box). Explicit\n // values always win.\n //\n // null sandboxGroupId ⇒ createSession seeds the new row's own id (singleton,\n // today's 1:1 behavior). A shared/{groupId} spawn inherits the box's backend\n // (it is literally the same box; the child cannot pick its own). Cross-\n // workspace sharing is forbidden by construction: getSession/\n // getAnySessionInGroup are RLS-workspace-scoped, so a foreign parent/group\n // returns null → 404; the group uuid is NOT an access boundary, the workspace\n // filter is (stress (e)).\n const sandboxChoice = payload.sandbox ?? (parentSessionId ? \"shared\" : \"new\");\n let sandboxGroupId: string | null = null;\n let inheritedBackend: Session[\"sandboxBackend\"] | undefined;\n // ENV-AWARE GROUPING: under the CURRENT mechanics the workspace Environment is\n // creation-time box state — the box's manifest env is fixed when it is cold-\n // created, and the SDK's provided-session guard rejects any manifest-env delta\n // at attach. A session carrying a DIFFERENT Environment than the box it joins\n // is therefore a genuine shared-state conflict TODAY: its first turn on a warm\n // box dies with \"Live sandbox sessions cannot change manifest environment\n // variables\" (proven live, sessions 5aee77e9 + 63d18823). Until the Environment\n // is evicted from the manifest (per-exec, like the git token), grouping must be\n // env-aware: the INHERITED default falls back to an own box on mismatch (a\n // credentialed worker spawned from a credential-less manager just works), and\n // an EXPLICIT shared/{groupId} request with a mismatched Environment fails\n // fast at create (422) instead of poisoning the session's first turn.\n // The env conflict is a BOX property, so a boxless group is exempt: a\n // backend:\"none\" session runs in-process with no sandbox, no manifest, and no\n // provided-session attach — no shared box state exists to conflict, and\n // env-differing spawns from such parents shared safely before the env-aware\n // check. They keep sharing (and keep inheriting \"none\").\n const requestedEnvironmentId = payload.environmentId ?? null;\n const environmentMatchesGroup = (memberEnvironmentId: string | null): boolean =>\n memberEnvironmentId === requestedEnvironmentId;\n if (sandboxChoice === \"shared\") {\n if (!parentSessionId) {\n throw new HTTPException(422, { message: \"sandbox:'shared' requires a parent session (spawn from inside a session); use 'new' for a top-level create.\" });\n }\n const parent = await getSession(db, workspaceId, parentSessionId);\n if (!parent) {\n throw new HTTPException(404, { message: `parent session not found in workspace: ${parentSessionId}` });\n }\n if (parent.sandboxBackend !== \"none\" && !environmentMatchesGroup(parent.environmentId ?? null)) {\n if (payload.sandbox === \"shared\") {\n // The caller explicitly asked to share while carrying a different\n // Environment — surface the conflict at create time, not turn time.\n throw new HTTPException(422, { message: \"sandbox:'shared' requires the same environment as the creator's box (the box environment is fixed at creation); omit sandbox or pass 'new' when attaching a different environment.\" });\n }\n // Inherited default: deterministic separation on the genuine shared-state\n // conflict — the worker gets its own box (resolved like a top-level\n // create: payload.sandboxBackend, else the deployment default) and its\n // turn runs.\n } else {\n sandboxGroupId = parent.sandboxGroupId;\n inheritedBackend = parent.sandboxBackend;\n }\n } else if (typeof sandboxChoice === \"object\") {\n const member = await getAnySessionInGroup(db, workspaceId, sandboxChoice.groupId);\n if (!member) {\n throw new HTTPException(404, { message: `sandbox group not found in workspace: ${sandboxChoice.groupId}` });\n }\n if (member.sandboxBackend !== \"none\") {\n // Compare against EVERY member, not one arbitrary row: a legacy env-blind\n // group can carry mixed environmentIds, and an any-member read would make\n // the join verdict nondeterministic. Post-env-aware groups are homogeneous\n // (both join paths enforce equality), so this reads one distinct value in\n // the common case; a mixed legacy group deterministically rejects.\n const memberEnvironmentIds = await listDistinctEnvironmentIdsInGroup(db, workspaceId, sandboxChoice.groupId);\n if (!memberEnvironmentIds.every((memberEnvironmentId) => environmentMatchesGroup(memberEnvironmentId))) {\n throw new HTTPException(422, { message: `sandbox group ${sandboxChoice.groupId} runs a different environment (the box environment is fixed at creation); create with the group's environment or omit sandbox for an own box.` });\n }\n }\n sandboxGroupId = sandboxChoice.groupId;\n inheritedBackend = member.sandboxBackend;\n }\n // else \"new\": leave sandboxGroupId null → own singleton group (group ≡ id).\n // A working dir is only meaningful for a TARGETED machine (it is the chosen\n // box's path/cwd base). Present without a targetSandboxId is a malformed request\n // — reject it at the edge (mirrors the backend:'none' guard) rather than silently\n // dropping it, since the default group box has no working-dir seam yet.\n if (payload.workingDir !== undefined && !payload.targetSandboxId) {\n throw new HTTPException(422, { message: \"workingDir requires targetSandboxId (it is the targeted machine's working directory)\" });\n }\n // Honest-label (Stage-D closure): a top-level session TARGETED at a Connected\n // Machine (a selfhosted sandbox) runs machine-primary every turn, so its HOME\n // sandbox_backend must read \"selfhosted\" — not the deployment cloud default —\n // so the session row + first turn honestly reflect where the agent runs (the\n // Machines dashboard, the turn's warm-metering, and the file-download plane all\n // key off this). GUARDS: (1) only at a TOP-LEVEL create (inheritedBackend\n // undefined) — a shared/{groupId} spawn is literally the creator's box and must\n // NOT be relabeled; (2) only when the target's kind is actually \"selfhosted\" —\n // targetSandboxId also accepts a first-class MODAL sandbox id (resolveTarget),\n // which must never be mislabeled. A not-found / non-selfhosted / modal target\n // falls through to the default; the seed swap in createAndStartSession still\n // validates ownership/liveness and 422s a bad target. (3) only when the feature\n // flags that make the worker actually take the machine-primary path are ON\n // (sandboxOwnershipEnabled + sandboxSelfhostedEnabled/routing) — otherwise the\n // worker ignores the active pointer and a home=\"selfhosted\" turn would fall to\n // the registry client with no bound agentId and throw; with the flags off we\n // keep the cloud default and the machine layers as a (pre-honest-label) overlay.\n // sandbox_os (the OS axis the worker's group-box resume + the OS-labeling\n // surfaces key off) must ALSO reflect the targeted machine, not the \"linux\"\n // schema default — a session run on a macOS Connected Machine that labels\n // itself linux lies to those surfaces. Derived under the SAME guards as the\n // backend relabel; the enrollment (joined via the sandbox's enrollmentId)\n // carries the OS. enrollmentOsValues and the sessions.sandbox_os value set are\n // both (\"linux\",\"macos\",\"windows\"), so a known value maps 1:1; any other value\n // is left to the \"linux\" default (never write a value no reader understands).\n let machineHomeBackend: Session[\"sandboxBackend\"] | undefined;\n let machineHomeOs: Session[\"sandboxOs\"] | undefined;\n if (\n payload.targetSandboxId\n && inheritedBackend === undefined\n && settings.sandboxOwnershipEnabled\n && settings.sandboxSelfhostedEnabled\n ) {\n const targetSandbox = await getSandbox(db, workspaceId, payload.targetSandboxId);\n if (targetSandbox?.kind === \"selfhosted\") {\n machineHomeBackend = \"selfhosted\";\n if (targetSandbox.enrollmentId) {\n const enrollment = await getEnrollment(db, workspaceId, targetSandbox.enrollmentId);\n if (enrollment && (enrollment.os === \"macos\" || enrollment.os === \"windows\" || enrollment.os === \"linux\")) {\n machineHomeOs = enrollment.os;\n }\n }\n }\n }\n await requireLimit(deps, { accountId: grant.accountId, workspaceId, action: \"agent_run:create\", quantity: 1, model });\n const session = await createAndStartSession({\n db,\n bus,\n workflowClient,\n accountId: grant.accountId,\n workspaceId,\n initialMessage: payload.initialMessage,\n resources,\n tools,\n ...(payload.clientEventId ? { clientEventId: payload.clientEventId } : {}),\n model,\n reasoningEffort,\n // A shared spawn inherits the box's backend; a caller-supplied\n // sandboxBackend on a shared spawn is ignored (it is the same box). A\n // machine-targeted top-level create labels the home \"selfhosted\"\n // (machineHomeBackend), overriding the caller/deployment default so the row\n // matches where the session actually runs.\n sandboxBackend: inheritedBackend ?? machineHomeBackend ?? payload.sandboxBackend ?? settings.sandboxBackend,\n // Mirror the backend relabel on the OS axis: only a machine-targeted\n // top-level create carries a derived OS; everything else is omitted and the\n // \"linux\" default holds (shared spawns keep the parent-box behavior).\n ...(machineHomeOs ? { sandboxOs: machineHomeOs } : {}),\n sandboxGroupId,\n metadata: payload.metadata,\n environment: environment ? { id: environment.id, name: environment.name } : null,\n goal: payload.goal ?? null,\n firstPartyMcpPermissions,\n parentSessionId,\n createIdempotencyKey: payload.idempotencyKey ?? null,\n // Create-time machine targeting (A-2a): when a target sandbox is named, the\n // active-sandbox pointer is seeded race-free inside createAndStartSession\n // (after the row exists, before the first turn dispatches). Validation\n // (ownership/liveness) lives in swapActiveSandbox; an invalid target 422s.\n seedTargetSandbox: payload.targetSandboxId\n ? { sandboxId: payload.targetSandboxId, settings, workingDir: payload.workingDir ?? null }\n : null,\n });\n await recordWorkspaceUsage(deps, {\n accountId: grant.accountId,\n workspaceId,\n subjectId: grant.subjectId,\n eventType: \"agent_run.created\",\n quantity: 1,\n unit: \"run\",\n sourceResourceType: \"session\",\n sourceResourceId: session.id,\n idempotencyKey: `agent_run.created:${workspaceId}:${session.id}`,\n });\n return session;\n}\n\n/**\n * Full accept-user-message flow shared by the `user.message` branch of\n * `POST /sessions/:id/events` and the first-party MCP `session_send_message`\n * tool: resource/tool validation, usage limits, the locked append + turn\n * enqueue, and usage recording. `toolsProvided: false` applies the\n * workspace's default capability MCP tools, matching an absent `tools` key.\n */\nexport async function acceptSessionUserMessage(\n deps: ApiRouteDeps,\n grant: AccessGrant,\n workspaceId: string,\n sessionId: string,\n input: {\n text: string;\n resources?: ResourceRef[];\n tools?: ToolRef[];\n toolsProvided: boolean;\n model?: string | null;\n reasoningEffort?: ReasoningEffort | null;\n clientEventId?: string;\n },\n): Promise<{ accepted: SessionEvent; turn: SessionTurn }> {\n const { settings, db, bus, workflowClient, objectStorage } = deps;\n const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings);\n const requestedResources = normalizeResources(input.resources ?? []);\n const validatedTools = validateToolRefs(input.tools ?? [], runtimeSettings);\n const requestedTools = input.toolsProvided\n ? validatedTools\n : withDefaultEnabledCapabilityMcpTools(validatedTools, settings, runtimeSettings);\n // Hoisted above requireLimit so the codex-billed predicate can resolve the\n // turn's effective model (a follow-up turn inherits the session's model). A\n // pure read with no side effects.\n const existingSession = await requireSession(db, workspaceId, sessionId);\n await requireLimit(deps, {\n accountId: grant.accountId,\n workspaceId,\n action: \"agent_run:create\",\n quantity: 1,\n model: input.model ?? existingSession.model,\n });\n if (requestedResources.some((resource) => resource.kind === \"file\") && !objectStorage) {\n throw new HTTPException(503, { message: \"object storage is not configured\" });\n }\n await validateFileResources(db, workspaceId, requestedResources);\n await validateGitHubRepositorySelection(db, workspaceId, [...existingSession.resources, ...requestedResources]);\n const { accepted, turn } = await postUserMessageTurn({\n db,\n bus,\n workflowClient,\n settings,\n accountId: grant.accountId,\n workspaceId,\n sessionId,\n text: input.text,\n resources: requestedResources,\n tools: requestedTools,\n model: input.model ?? null,\n reasoningEffort: input.reasoningEffort ?? null,\n ...(input.clientEventId ? { clientEventId: input.clientEventId } : {}),\n });\n await recordWorkspaceUsage(deps, {\n accountId: grant.accountId,\n workspaceId,\n subjectId: grant.subjectId,\n eventType: \"agent_run.created\",\n quantity: 1,\n unit: \"run\",\n sourceResourceType: \"session_turn\",\n sourceResourceId: turn.id,\n idempotencyKey: `agent_run.created:${workspaceId}:${turn.id}`,\n });\n return { accepted, turn };\n}\n\n/**\n * Shared title-write path for the manual rename route AND both MCP tools\n * (set_session_title / set_other_session_title). The clobber guard lives in\n * the db `updateSessionTitle` UPDATE: an agent write is skipped when a user\n * title already pinned the session. On a real write we emit `session.title_set`\n * exactly like goal mutations emit their events; when nothing changed (agent\n * write blocked by the user lock) we emit nothing. Returns whether a write\n * happened so callers can avoid double work.\n */\nexport async function updateSessionTitle(\n deps: { db: Database; bus: EventBus },\n workspaceId: string,\n sessionId: string,\n title: string,\n source: \"user\" | \"agent\",\n): Promise<{ updated: boolean; title: string | null }> {\n const { db, bus } = deps;\n const result = await updateSessionTitleRow(db, { workspaceId, sessionId, title, source });\n if (result.updated) {\n await appendAndPublishEvents(db, bus, workspaceId, sessionId, [{\n type: \"session.title_set\",\n payload: {\n title: result.title ?? title,\n source,\n },\n }]);\n }\n return result;\n}\n\nfunction withFirstPartyTools(tools: ToolRef[], runtimeSettings: { mcpServers: Array<{ id: string }> }): ToolRef[] {\n if (!runtimeSettings.mcpServers.some((server) => server.id === \"opengeni\")) {\n return tools;\n }\n return mergeToolRefs(tools, [{ kind: \"mcp\", id: \"opengeni\" }]);\n}\n\nfunction hasOwnProperty(value: unknown, key: string): boolean {\n return Boolean(value && typeof value === \"object\" && Object.prototype.hasOwnProperty.call(value, key));\n}\n","// Pure, HTTP-shaped guard helpers for the workspace member + workspace delete\n// routes. Kept out of the route bodies so the don't-orphan rules (never remove\n// the last admin, never delete an account's last workspace or one with a live\n// session) are unit-testable without a database.\nimport type { Permission, WorkspaceMember } from \"@opengeni/contracts\";\nimport { HTTPException } from \"hono/http-exception\";\n\n/** The membership permission that grants member-management (admin is the wildcard). */\nconst MEMBER_ADMIN_PERMISSIONS: Permission[] = [\"workspace:admin\", \"members:manage\"];\n\n/** A member can manage other members (directly or via the admin wildcard). */\nexport function memberCanAdminister(member: Pick<WorkspaceMember, \"permissions\">): boolean {\n return member.permissions.some((permission) => MEMBER_ADMIN_PERMISSIONS.includes(permission));\n}\n\n/** Only `user:` subjects are people; `api_key:` subjects belong to API keys. */\nexport function isUserMember(member: Pick<WorkspaceMember, \"subjectId\">): boolean {\n return member.subjectId.startsWith(\"user:\");\n}\n\n/**\n * Turn an email lookup result into the membership subject id. A null id means\n * no registered user matched the email — email invites for not-yet-registered\n * users are deferred, so that is a 404 (not a 400) at the API surface.\n */\nexport function resolveMemberSubjectId(userId: string | null): string {\n if (!userId) {\n throw new HTTPException(404, { message: \"user is not registered\" });\n }\n return `user:${userId}`;\n}\n\n/**\n * Guard the member-remove path. Refuses (409) to remove the caller's own\n * membership and refuses to remove the last member that still holds an admin\n * permission, so a workspace can never be orphaned with no one able to manage\n * it. `members` is the full roster (every subject, including api_key ones —\n * an api_key with workspace:admin still counts as an administering subject).\n */\nexport function assertWorkspaceMemberRemovable(input: {\n members: WorkspaceMember[];\n subjectId: string;\n callerSubjectId: string;\n}): void {\n const { members, subjectId, callerSubjectId } = input;\n if (subjectId === callerSubjectId) {\n throw new HTTPException(409, { message: \"you cannot remove your own membership\" });\n }\n const target = members.find((member) => member.subjectId === subjectId);\n if (!target) {\n throw new HTTPException(404, { message: \"member not found\" });\n }\n if (memberCanAdminister(target)) {\n const remainingAdmins = members.filter((member) => member.subjectId !== subjectId && memberCanAdminister(member));\n if (remainingAdmins.length === 0) {\n throw new HTTPException(409, { message: \"cannot remove the last member who can manage this workspace\" });\n }\n }\n}\n\n/**\n * Guard the workspace-delete path before any external/DB mutation. Refuses\n * (409) to delete the account's last workspace, and refuses while any session\n * could still be running in Temporal (there is no clean per-session terminate\n * to call first, so we will not orphan a workflow — the operator must stop the\n * sessions first).\n */\nexport function assertWorkspaceDeletable(input: {\n workspaceCountForAccount: number;\n activeSessionCount: number;\n}): void {\n if (input.workspaceCountForAccount <= 1) {\n throw new HTTPException(409, { message: \"cannot delete the account's only workspace\" });\n }\n if (input.activeSessionCount > 0) {\n throw new HTTPException(409, {\n message: \"stop the workspace's running sessions before deleting it\",\n });\n }\n}\n"],"mappings":"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","names":["getSandbox","readActiveSandbox","NatsControlRpc","NatsControlRpc","readActiveSandbox","getSandbox","pointer","HTTPException","HTTPException","environmentsEncryptionKeyBytes","getWorkspaceEnvironment","listPackInstallations","HTTPException","HTTPException","HTTPException","HTTPException","listPackInstallations","HTTPException","getWorkspaceEnvironment","environmentsEncryptionKeyBytes","HTTPException","enabled","HTTPException","installationId","HTTPException","getEnrollment","getSandbox","requireSession","HTTPException","HTTPException","requireSession","getSandbox","getEnrollment","HTTPException","HTTPException"]}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@opengeni/core",
3
+ "version": "0.2.0",
4
+ "description": "OpenGeni framework-agnostic core: the domain, access, and billing layers (neutral access, off-HTTP V2 surface). Behavior-preserving extraction from apps/api — keeps Hono's HTTPException for error throwing (typed-errors cleanup deferred).",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Cloudgeni-ai/opengeni.git",
9
+ "directory": "packages/core"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": false,
13
+ "main": "./dist/index.js",
14
+ "module": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "src"
25
+ ],
26
+ "engines": {
27
+ "node": ">=18"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public",
31
+ "provenance": true
32
+ },
33
+ "scripts": {
34
+ "typecheck": "tsc --noEmit",
35
+ "build": "tsup"
36
+ },
37
+ "dependencies": {
38
+ "@modelcontextprotocol/sdk": "^1.29.0",
39
+ "@opengeni/codex": "^0.2.0",
40
+ "@opengeni/config": "^0.2.0",
41
+ "@opengeni/contracts": "^0.3.0",
42
+ "@opengeni/db": "^0.2.0",
43
+ "@opengeni/documents": "^0.2.0",
44
+ "@opengeni/events": "^0.2.0",
45
+ "@opengeni/observability": "^0.2.0",
46
+ "@opengeni/runtime": "^0.2.0",
47
+ "@opengeni/storage": "^0.2.0",
48
+ "hono": "^4.12.18"
49
+ },
50
+ "devDependencies": {
51
+ "better-auth": "^1.6.14",
52
+ "tsup": "^8.5.0",
53
+ "typescript": "^6.0.3"
54
+ }
55
+ }