# Bellona — Systems Deep Dive

> 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 reference

### bellona-bridge-blender

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.

### bellona-bridge-godot

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.

### bellona-bridge-unity

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.

### bellona-bridge-unreal

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.

### bellona-build-api

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
`Map`s otherwise — an honest degraded mode, logged as `backend: 'memory'`, not a
fake. Exposes `initialize`/`shutdown`/`getHealthStatus` with real cache-hit-rate
stats.

### bellona-build-worker

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.

### @bellona/cli

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.

### @bellona/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.

### @bellona/remote-extension

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.

### @bellona/remote-gateway

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.

### @bellona/remote-host

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.

### 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.
