Scripting

Write Kotlin scripts that run inside the platform — triggered by events, exposed as API endpoints, or used as AI agent tools. Sandboxed execution with full access to Bosca services.

Overview

Bosca includes an embedded Kotlin Script (KTS) engine. Scripts are .bosca.kts files evaluated by Kotlin's embedded compiler. They have access to the full Bosca service layer (content, collections, metadata, search, etc.) with some guardrails against common dangerous operations — though scripts run with significant privilege and can still cause damage if misused.

Script Types

TypePurposeExecution
GENERALUtility scriptsManual via GraphQL
TRIGGERReact to platform eventsAsync via job queue
TOOLAI agent toolsCalled by AI agents
APIHTTP endpointsGET/POST /api/v1/s/{key}
EPHEMERALTemporary/one-shot scriptsAuto-purged after retention period

Writing Scripts

Scripts extend BoscaScript implicitly. They have access to a context object, the authentication context, a coroutine scope, and a log logger. Use the main {} block for async work:

Example: trigger script
Example: API script
Scripts resolve services using provide<T>() — the same DI mechanism used by the rest of the platform. The full server classpath is available at compile time.

Trigger Bindings

Trigger scripts are bound to platform events via trigger bindings. When the event fires, the script is enqueued as a background job and executed asynchronously.

Binding a script to an event (GraphQL)

Trigger scripts execute as a dedicated service account (not the originating user), ensuring consistent permissions for automated processing.

Available events

Any event dispatched via the platform's event system can trigger scripts. Common events include:

  • bosca.content.collection.created / updated / state
  • bosca.content.metadata.created / updated / state
  • bosca.git.push
  • Analytics pipeline events, form submissions, profile changes, etc.

API Scripts

Scripts with type API are exposed as HTTP endpoints at /api/v1/s/{key}:

  • POST — request body is parsed as JSON and available as context.input
  • GET — query parameters are converted to a JSON object
  • Public scripts — no authentication required
  • Non-public scripts — caller must have EXECUTE permission
  • Timeout — 30 seconds

AI Agent Tools

Scripts with type TOOL are automatically registered as AI agent tools. They include an inputSchema (JSON Schema) that the AI uses to understand what parameters to pass:

Tool script with input schema

Security Guardrails

Scripts have some protections against accidental misuse, but they are not a full sandbox. A script running without authentication can still call services and modify data. These guardrails reduce the surface area for common mistakes:

Source validation

Applied before saving and before compilation. Blocks:

  • Import aliasing of System (e.g., import java.lang.System as Sys)
  • Method references to System
  • Any System.xxx call except: currentTimeMillis, nanoTime, lineSeparator, identityHashCode, arraycopy
  • Any reference to Runtime

Restricted class loader

Allowlist-based. Scripts can only load classes from:

  • bosca.*, kotlin.*, kotlinx.*, java.lang.*, java.util.*, java.time.*, java.math.*, java.text.*, org.slf4j.Logger

Hard-denied even within allowed prefixes: ProcessBuilder, reflect.*, ClassLoader, java.io.*, java.nio.*, java.net.*, Runtime, Thread

Execution timeout

Default 600 seconds (configurable). API scripts have a 30-second timeout.

Permissions

Scripts have group-based ACL via ScriptPermission (VIEW/EXECUTE/MANAGE). Managing scripts requires the admin group.

Compilation & Caching

Scripts are compiled to JVM bytecode and cached in two tiers:

  1. In-memory — Caffeine cache (500 entries, 1-hour TTL)
  2. Persistent — compiled bytecode stored in scripting.compiled_scripts table with a compiler fingerprint (SHA-256 of Kotlin version + JVM target)

Compilation runs on a single-thread dispatcher with a mutex to prevent redundant parallel compilations of the same script.

For GraalVM native image builds (which can't embed the Kotlin compiler), a remote engine enqueues compilation/execution jobs to a JVM worker via the job queue and reads results back via PubSub + object storage.

GraphQL API

graphql