Applications · entity catalog

bellona app

Authored subsystem deep-dive for bellona, layered on the code-linked entity catalog — what each system is, why it exists, and how it fits.

authored deep-dive
12entities3layers12deep-dives

On this page

The apps/bellona/ area: twelve Nx applications that make up Bellona's game-development control plane — engine bridges, a build/export/render pipeline, a developer CLI, and the Phase-180 remote creative-control surface (gateway, host, browser extension, and operator Control Room).

What this area is#

Bellona is Oshun's game-development and creative-tooling domain. The apps/bellona/ directory is not one service but twelve separate Nx applications (each with its own project.json) that split into three clusters: engine bridges, the build/export/render pipeline, and the Phase-180 remote creative-control plane plus its CLI.

The engine-bridge cluster (bellona-bridge-blender, bellona-bridge-godot, bellona-bridge-unity, bellona-bridge-unreal) are standalone WebSocket servers. Each one boots a createBridgeServer(...) from the @bellona/bridge-core library, registers a domain-specific command vocabulary (Blender scene/asset commands, Godot scene-tree/GDScript, Unity GameObject/physics, Unreal actor/sequencer), and proxies those commands over the socket to a connected DCC/engine editor plugin via forwardToEngine(...). They are real proxies, not simulators: if no engine plugin is connected, findEngineConnection(...) throws rather than fabricating a response. The actual engine-side plugins live outside this directory.

The build/export/render cluster (bellona-build-api, bellona-build-worker, bellona-render-api) is the asset-pipeline backend. bellona-build-api is a content-addressable build/export cache plus a cross-domain event consumer; bellona-build-worker is the job processor that bakes assets, validates them, generates engine projects, and packages exports; bellona-render-api is a Redis-backed render cache fronting a GPU render queue. They communicate through Redis queues and the @oshun/event-bus, and emit @bellona/event-publisher lifecycle events (build.started, export.ready, etc.).

The remote-control cluster (@bellona/remote-gateway, @bellona/remote-host, @bellona/remote-extension, @bellona/control-room) is the Phase-180 "remote creative control plane": an operator drives a controlled workstation (Blender, Unreal, a managed browser, or macOS desktop fallback) through an audited, approval-gated gateway. @bellona/cli is the unifying command-line entry point that exercises both the build/export API and the remote-control surface.

How the area is shaped#

The clusters depend on shared libs/bellona/* and @oshun/* libraries rather than on each other directly:

  • the four bridges all compose @bellona/bridge-core and @bellona/event-publisher;
  • the build/render services compose @oshun/cache, @oshun/event-bus, @oshun/logging, @bellona/event-handlers, and @bellona/event-publisher;
  • the remote-control services are built almost entirely on the @bellona/remote-protocol library, which owns the Zod schemas for devices, commands, sessions, approvals, audit chains, and artifacts — every gateway and host write validates against it.

A recurring honesty caveat applies to the remote-control cluster: the gateway and host READMEs describe themselves as "walking skeleton for Phase 180." That undersells the gateway/host control-plane logic (which is substantial and real) but is accurate about the engine adapters, several of which are deterministic mocks (Unreal) or macOS-only native backends (desktop fallback) rather than universally-live integrations. The per-entity blocks below call out which is which.

How it fits the wider system#

These apps are the runtime surface of the Bellona domain. The bridges are consumed by DCC/engine plugins on one side and by Bellona's API/agent tooling on the other. The build/render services are consumed by anything that needs to bake, package, or render game assets, and they publish onto the Oshun event bus so other domains can react to build lifecycle events. The remote-control plane is consumed by a human operator (through @bellona/control-room or the @bellona/remote-extension popup) and by agents (through @bellona/cli remote and the gateway's HTTP/WebSocket API), with @bellona/remote-host running on the controlled workstation. Walk the "used by" edges on any node to see exactly who depends on it.

Entity catalog (12)#

The 12 tracked Nx projects in bellona, each a code-linked entity node — package, type, source path, declared targets, and its internal dependency graph (depends-on / used-by, resolved from the package manifests, §6/§8), read from the project graph. Grouped by architectural layer; walk the dependency links to travel the system. 12 of these carry an authored deep-dive (what / why / how it fits); the rest are generated scaffolds awaiting one.

client (1)#

app

@bellona/remote-extension

#

Bellona remote-control minimal MV3 browser extension (origin-authenticated, domain-scoped, with a tamper-resistant visible-automation indicator)

A minimal Manifest V3 browser extension for the remote-control surface (apps/bellona/remote-extension). Its public surface (src/index.ts) is a set of pure, adversarially-unit-tested security primitives: a closed-by-default origin allow-list that fails loud on <all_urls> (origin-policy.ts), extension-origin authentication and per-session token minting (extension-auth.ts), sensitive-action guards for clipboard/upload/form (action-guards.ts), a tamper-resistant shadow-DOM automation indicator (automation-indicator.ts), session teardown (session-lifecycle.ts), and manifest domain-scoping invariants (manifest-policy.ts). The README is candid that the Chrome-runtime wiring (background.ts, content-script.ts) is "a thin shell" that cannot load in CI, so the logic is tested through the pure functions — a deliberate dependency-boundary approach, not a stub.

buildtestlinttypecheck
layer: clientscope: bellonaowner: @GreyChimp

service (2)#

app

@bellona/remote-gateway

#

Bellona remote gateway service walking skeleton

The remote creative-control plane gateway (apps/bellona/remote-gateway/src/app.ts), described as a Phase-180 walking skeleton but in fact a large, real control plane. createRemoteGatewayApp(...) composes a node http server exposing health/readiness plus /v1 endpoints for devices, commands, sessions, streams, approvals, artifacts, timeline, audit export, and pairing exchange, alongside a WS /v1/hosts/connect host channel. It owns a @bellona/remote-protocol-validated device registry, a command dispatcher that runs every command through the shared permission policy (capability scopes, approval gating, fail-closed on audit-store outages except read-only diagnostics), a hash-chained audit log, an approval service with deny-by-default expiry, one-time CSPRNG pairing codes, HMAC host tokens, session-lifecycle and stream registries, and in-memory telemetry. State is ephemeral by default but can opt into a documented first-stage atomic-JSON persistent store (schema v3 with forward migration). The honest boundary: it orchestrates and audits commands but executes nothing itself — real work happens on the connected host.

buildtestlinttypecheckservedevstart
layer: servicescope: bellonaowner: @GreyChimp
app

@bellona/remote-host

#

Bellona remote host service walking skeleton

The remote host process that runs on the controlled workstation (apps/bellona/remote-host). It loads a macOS-Keychain-backed device identity, opens an outbound WebSocket to the gateway with bounded reconnect, and runs a host command executor that emits protocol-valid progress/result/error events. Its adapter registry is where the implemented-vs-mocked split is sharpest, and the README is unusually explicit about it: the Blender adapter is real (loopback-only discovery of the repo's addon/bridge, then a large canonical command surface — scene info, object/collection/material/modifier/mesh-edit mutations, asset import/export — each wrapped with before/after scene-info evidence and undo checkpoints); the browser adapter really launches Chrome/Chromium through Playwright bound to loopback CDP with blocked-domain policy; the desktop fallback adapter is macOS-only and shells real Swift CoreGraphics/AppKit helpers for screenshot/window/click/type/clipboard with fail-closed redaction; the Unreal adapter's project.info/world.query/ actor.spawn are deterministic mocks that validate the protocol schemas but do not yet drive a live editor. The command-policy preflight is honestly named a ...policy-preflight-stub pending the real policy package. Many capabilities are macOS-specific and report not-applicable elsewhere.

buildtestlinttypecheckserveblender:create-primitive-remote-smokeblender:create-primitive-smokeblender:scene-info-remote-smokeblender:scene-info-smoke
layer: servicescope: bellonaowner: @GreyChimp

unclassified (9)#

app

@bellona/cli

#

Command-line interface for Bellona game development platform

The Bellona game-development CLI (apps/bellona/cli/src/index.ts), built on commander + chalk. The bellona program registers command groups for build, export, sync (engine sync/push/conflicts), config, health, project/detect, and remote — the last being the remote creative-control plane client (pair, devices, sessions, stream, command, approve, diagnose, artifacts, audit export, unpair). It talks to the build API over HTTP (default http://localhost:3020) and to the remote gateway through src/utils/remote-client.ts. Quick aliases (b, e) re-parse into the canonical subcommands. A real, fully-wired CLI, not a scaffold.

buildtestlinttypecheckdevstart
scope: bellonaowner: @GreyChimp
app

@bellona/control-room

#

Bellona browser-first remote-control operator Control Room.

The browser-first operator surface for the Phase-180 remote-control MVP (apps/bellona/control-room, a React + Vite app). It is explicitly scaffolded behind the VITE_BELLONA_CONTROL_ROOM_ENABLED feature flag (disabled by default, including production), and the README is clear that "no gateway, host, desktop, browser, Blender, or Unreal privileges are exposed from this scaffold" and queued commands record an audit preview rather than dispatching to a live host. Within that boundary the UI logic is substantial and real: an approval queue with keyboard shortcuts, a command palette sourced from REMOTE_COMMAND_NAMESPACE_VALUES, command search, a first-session guided tour, device permission diagnostics, a mobile-approval PWA route with a service worker, plus i18n and a11y modules — all fixture-backed (@bellona/remote-protocol fixtures) and exercised by Vitest + Playwright. Honest status: real, flag-gated, fixture-driven operator UI; not yet connected to a live gateway.

buildtestlinttypecheckservee2edevpreview
scope: bellonaowner: @GreyChimp
app

bellona-bridge-blender

@bellona/bridge-blender#

Bridge service for Blender integration

A standalone WebSocket bridge service for Blender (apps/bellona/bridge-blender/src/main.ts). createBlenderBridge() starts a @bellona/bridge-core server on ws://localhost:9001/blender, registers handshake/ping plus six Blender commands (blender:get-scene-info, create-object, import-asset, export-asset, set-frame, render), and forwards each to a connected blender-plugin client via forwardToEngine(...), returning the engine's real reply. It is the most fleshed-out bridge: it also tracks per-connection SessionMetadata and publishes BellonaSessionStarted/SessionEnded events through @bellona/event-publisher. Real proxy logic; the Blender-side addon that answers the commands lives outside this directory.

buildtestlintserve
scope: bellonaowner: @GreyChimp
app

bellona-bridge-godot

@bellona/bridge-godot#

Bridge service for Godot Engine integration

The Godot Engine WebSocket bridge (apps/bellona/bridge-godot/src/main.ts). createGodotBridge() listens on ws://localhost:9002/godot and registers nine Godot-specific commands covering the scene tree, node creation/property/method calls, scene and resource loading, signal emission, GDScript execution (with a 60s timeout), and project settings — each proxied to a connected godot-plugin client. Same forward-or-throw contract as the other bridges; it does not yet wire the event-publisher session tracking that the Blender bridge has.

buildtestlintserve
scope: bellonaowner: @GreyChimp
app

bellona-bridge-unity

@bellona/bridge-unity#

Bridge service for Unity Engine integration

The Unity Engine WebSocket bridge (apps/bellona/bridge-unity/src/main.ts), listening on ws://localhost:9004/unity. It registers the largest command set of the four — fourteen commands spanning GameObject create/destroy, component add/set, scene load/unload, prefab instantiation, transforms, Animator play/parameter, Rigidbody force, physics raycast, and SendMessage. Notable detail: this entrypoint ships its own small LOG_LEVEL-aware logger (routing through console.warn/console.error) to honour the Bellona logging contract without pulling a non-Bellona dependency into the standalone process. Commands are proxied to a connected unity-plugin client.

buildtestlintserve
scope: bellonaowner: @GreyChimp
app

bellona-bridge-unreal

@bellona/bridge-unreal#

Bridge service for Unreal Engine integration

The Unreal Engine WebSocket bridge (apps/bellona/bridge-unreal/src/main.ts), listening on ws://localhost:9003/unreal. It registers eleven commands: world info, actor spawn/destroy/property, Blueprint function calls, streaming level load/unload, material parameters, Sequencer control, console-command execution, and screenshots — all forwarded to a connected unreal-plugin client. Structurally identical to the Godot/Unity bridges (forward-or-throw, console logging), specialised to Unreal's actor/level/Sequencer vocabulary.

buildtestlintserve
scope: bellonaowner: @GreyChimp
app

bellona-build-api

#

Build API for Bellona build and export system with content-addressable caching

The build/export API service (apps/bellona/build-api/src/main.ts). It owns a content-addressable build cache (createBuildCacheService, 100 MB in-memory tier over a 10 GB Redis tier with compression and deduplication) and wires cross-domain event handlers via @bellona/event-handlers and @oshun/event-bus so build/export requests arriving as events are enqueued. Its build/export queue adapters (createBuildQueueAdapter, createExportQueueAdapter) use Redis pipelines (hset/zadd/sadd, priority-scored pending sets) when REDIS_URL is set and fall back to in-memory Maps otherwise — an honest degraded mode, logged as backend: 'memory', not a fake. Exposes initialize/shutdown/getHealthStatus with real cache-hit-rate stats.

buildtestlintserve
scope: bellonaowner: @GreyChimp
app

bellona-build-worker

@bellona/build-worker#

Background worker service for asset building and processing

The build worker service (apps/bellona/build-worker/src/main.ts). BuildWorkerService is a polling job runner: it dequeues from a JobQueue and dispatches to four real workers — processAssetBakeJob, processValidationJob, processEngineProjectJob, processExportPackageJob — emitting progress and publishing BellonaBuildStarted/Progress/Completed and ExportStarted/Ready events. The work is genuine: asset-bake-worker.ts hashes files with SHA-256 and shells out to real tools (sharp/ImageMagick for textures, ffmpeg for audio, gltf-pipeline for models) via execFile. The service tracks completed/failed counts, average duration, heartbeats, retry-on-fail, and graceful shutdown that drains the in-flight job.

buildtestlintserve
scope: bellonaowner: @GreyChimp
app

bellona-render-api

#

The render API service (apps/bellona/render-api/src/main.ts). It initialises a Redis-backed render cache (createRenderCacheService) — real content-addressable storage with pub/sub invalidation, distributed locking, LRU eviction, and TTL tiers for jobs/outputs/progress/metadata drawn from @oshun/cache. Behind it sits a GPU render queue (src/queue/gpu-queue.ts) that tracks GPU devices, memory, priority queuing, concurrent-job limits, timeouts, retries, and health checks, plus an output validator (src/validation/). Exposes the same initialize/shutdown/getHealthStatus lifecycle as the build API. The caching and queue-management logic is real; the GPU device list is the resource it schedules against.

buildtestlintserve
scope: bellonaowner: @GreyChimp