# Bosca Developer Documentation > Platform for content management, workflow automation, and real-time collaboration. > Built with Kotlin, GraphQL, PostgreSQL, and KSP code generation. ## Architecture - Core/impl split: core-* modules define contracts (interfaces, models, annotations), impl modules provide concrete implementations - KSP (Kotlin Symbol Processing) generates all boilerplate at compile time — no runtime reflection - Key annotations: @Repository, @ServiceImplementation, @TypeController, @Field, @RouteController, @JobDefinition, @JobEvent - Infrastructure is abstracted: CacheManager (Redis or NATS KV), PubSubService (NATS or Redis), JobQueue (NATS JetStream or Redis) - Two applications: bosca-server (GraphQL API via Netty) and bosca-runner (background jobs) - All I/O uses Kotlin suspend functions; JDBC dispatched to virtual-thread-per-task executor ## Models & Repositories - Models are @Serializable data classes in core-* modules. Use @Contextual on UUID fields. Default id to UUID.NIL. - Repositories are interfaces annotated with @Repository. Methods annotated with @Query("SQL"). - Named parameters use :paramName syntax. Object properties matched by name (:name maps to category.name). - returning * maps inserted/updated row back to model. Nullable return (T?) for optional lookups. - Batch lookups: where id = any(:ids) with List parameter. - Known limitation: @Query does not support multiple model parameters, only multiple primitives. ## Services - Annotated with @ServiceImplementation. Implement interface from core-* module. - Constructor injection: repositories, other services, infrastructure (CacheManager, PubSubService, etc.) - Own business logic, cache management (ServiceCache), and event dispatch. - Do NOT handle auth — that's the controller's job. - Dispatch events after writes: CollectionCreated(entity).dispatch() ## GraphQL - Schema files: .graphqls under src/main/resources/graphql/ - Schema registration: @Schemas interface with @Schema("file.graphqls") properties per module - @TypeController on class + @Field on methods. Type inferred from GraphQLController. - Namespace pattern: top-level fields return singleton objects resolved by their own @TypeController - Query path: query { content { categories { all { ... } } } } - Auto-injected parameters: AuthenticationContext, AuthenticationContext?, Batch, DataFetchingEnvironment, ServerCall - Mutations: AuthenticationContext non-nullable (required). Pattern: authenticate → authorize → execute → return - Subscriptions: return Flow backed by PubSubService - Batching: Batch in field resolvers integrates with DataLoader ## Routes - @RouteController(path, method, authentication) on classes extending Route, APIRoute, SSERoute, or Page - Route: JSON response. APIRoute: structured error JSON. SSERoute: Server-Sent Events. Page: HTML via JTE. - Authentication modes: NONE, REQUIRED, OPTIONAL - ServerCall: receive() for JSON body, pathParameters["id"], respondRedirect(), respondStreaming() - Path parameters: {id}, {name}.json, {path...} (tailcard) ## Permissions - Entity-scoped, group-based. PermissibleEntity interface with flags: public, publicContent, publicList, publicSupplementary, isPublished, isAdvertised, isDeleted - PermissionAction: VIEW, LIST, EDIT, MANAGE (implies EDIT), DELETE, EXECUTE, IMPERSONATE - Decision chain: deleted check → public/advertised access → editor group → entity permissions → role-based fallback - Published vs advertised: advertised grants VIEW/LIST but NOT content/supplementary access - Queries: filter silently (return empty). Mutations: verify and throw. - GroupEvaluator: verifyHasSaGroup, verifyHasAdminGroup, verifyHasEditorGroup, verifyHasManagerGroup - Batch: filterAllowed(auth, entities, action) — single round-trip permission check - Locked entities: only SA can modify. Check locked before permissions. ## Transactions & Connections - ConnectionManager: per-request, lazy (no physical connection until first SQL operation) - transaction {} wraps block. NonCancellable commit/rollback. Nested = SQL SAVEPOINT. - GraphQL: each field resolver gets own ConnectionManager. ConnectionLimiter semaphore (limit 5). - HTTP routes: single ConnectionManager for entire request. - Deferred side effects via ConnectionManagerCallback.onCommit(): cache writes, job enqueues, pub-sub publishes - withConnectionManager {} for code outside request context (background jobs) ## Caching - Two-tier: RequestCache (in-memory per-request) + CacheManager (distributed, shared) - ServiceCache: named cache slots. Constructor: cacheName, keySerializer, batchResolver, expiration (10min default), resolver - Remote writes deferred until after transaction commits. Rolled-back writes discarded. - Invalidate ALL caches over the same data on writes. Missing one = stale reads. - Batch jobs: requestCache().clearLocal() after each batch to prevent memory growth. ## Messaging & Events - @JobEvent(jobs=[...], pubsubChannel="...") on @Serializable event classes implementing Event - dispatch() generated by KSP. Deferred until transaction commits. - deferredEvents {} deduplicates by (eventClass, identityKey()) - @JobDefinition(PayloadClass, queueName, jobName) on executor extending AbstractJobExecutor - Executors run in bosca-runner. override suspend fun execute() { getJobDefinition() } - PubSubService: publish/subscribe with Flow. Used for GraphQL subscriptions. ## Bulk Processing - MAX_BULK_OPERATION_SIZE = 500. Guard with require() at start of every bulk mutation. - Pattern: getByIds (1 query) → filterAllowed (1 query) → bulk service method (1 query) - Push bulk list through service/repository layers. Repository: WHERE id = ANY(:ids) - Transactional: all-or-nothing. Error-tolerant: per-item try/catch, log failures, return success count. - Locked: filter before permission check. SA bypasses locked filter. - Background: offset-pagination with DistributedLock. clearLocal() after each batch. ## Scripting - Embedded Kotlin Script (KTS) engine using kotlin-scripting-jvm-host. Scripts are .bosca.kts files. - Script types: GENERAL (manual), TRIGGER (event-driven async), TOOL (AI agent), API (HTTP endpoint), EPHEMERAL (auto-purged) - Scripts extend BoscaScript implicitly. Access context, authentication, scope, log. Use main {} for async work. - Resolve services with provide() — same DI as the rest of the platform. - Trigger bindings: link scripts to platform events (e.g., bosca.content.collection.created). Execute as service account. - API scripts: GET/POST /api/v1/s/{key}. Public scripts need no auth. Non-public require EXECUTE permission. 30s timeout. - TOOL scripts: auto-registered as AI agent tools with inputSchema (JSON Schema) for parameter discovery. - Security: source validation (blocks System/Runtime), RestrictedClassLoader (allowlist: bosca.*, kotlin.*, java.lang/util/time/math/text), execution timeout (600s default). - Compilation cached two tiers: Caffeine (500 entries, 1hr) + persistent DB (compiled_scripts table with compiler fingerprint). - GraalVM native mode: remote engine delegates compile/execute to JVM worker via job queue. ## Bosca Git - Full self-hosted Git server using JGit. Smart HTTP protocol (clone, push, fetch). - Storage: pack files in S3 at git/{repositoryId}/packs/. Refs in PostgreSQL. Stateless — multiple pods OK. - Repository content types: GENERAL, SCRIPT_PROJECT, BX_PROJECT, DOCUMENTATION, ANALYTIC_QUERY_PROJECT - Source refs: link scripts/queries to Git files. On push, changed files auto-sync to scripting engine / query store. - Set source ref: mutation { git { setScriptSourceRef(scriptId, repositoryId, path, ref) } } - Pull requests with reviews, merge strategies (merge/squash/rebase), assignees. - Branch protection: block force push, block deletion, require PR, push access restrictions. - Post-receive hooks: webhooks (HMAC-SHA256), WorkOps task key extraction from commits, search indexing, CI pipeline triggers, content change detection for SCRIPT_PROJECT/BX_PROJECT/ANALYTIC_QUERY_PROJECT repos. - CI/CD: pipeline definitions from YAML, triggers (push/PR/tag/manual/schedule), agents (runner/orchestrator), secrets, step-level logs. - LFS support: objects stored at git-lfs/{repositoryId}/{oid} in S3. ## Bosca CLI - Command-line tool built with Clikt + Apollo Kotlin. GraalVM native binary support. - Auth: bosca login (password, OAuth2 browser flow, API token). Config stored ~/.config/bosca/config.json. - data: install (bootstrap from manifest), metadata CRUD + set-content, collection CRUD + items, supplementary, relationships, templates. - workops: portfolio/program/project/task CRUD, transitions, sprints, boards, BQL search. - bx: compile, serve (HTMX preview with hot-reload), install, validate, package, watch. - localization: upload, download, status, sync (Crowdin integration). - ci: agent register/start, pipeline trigger/cancel/rerun, logs --follow, secrets. - tokens: create, list, revoke, scopes. - kubernetes: init, generate (cdk8s manifests), apply, set-version, restart, setup-minikube, issue-license. - mcp-server: STDIO MCP server for AI assistants. Tools for content, workops, templates. - All commands support --url/--token/--username/--password overrides + BOSCA_ENDPOINT/TOKEN/USERNAME/PASSWORD env vars. ## Infrastructure - Docker Compose: PostgreSQL (5433), PostgreSQL warehouse (5434), NATS (4222), Redis-compatible (6380), Meilisearch (7701), S3Proxy (8000), Trino (8089), Jaeger (16686), Text Extractor (8083). - Kubernetes: bosca kubernetes generate produces layered YAML via cdk8s (no Helm). Feature flags for optional services. - Configurable backends: CACHE_TYPE (redis|nats), PUBSUB_TYPE (nats|redis), JOB_QUEUE_FACTORY (redis|nats), DISTRIBUTED_LOCK_TYPE (nats|redis), STORAGE_TYPE (s3|gcs). - Integrations: Mux (video), HubSpot (CRM), SendGrid (email), Crowdin (l10n), Google/OpenAI/Anthropic (AI), PostHog (analytics).