# Proto Domain — Technical Specifications

> Technical specification for `@oshun/proto` (`libs/proto/`): the Protocol
> Buffer schema library and gRPC runtime helper layer for Oshun inter-service
> communication. This document catalogs every `.proto` service definition, every
> loader/runtime utility, the `PROTO_PATHS` / `SERVICE_NAMES` registries, the
> channel/credential helpers, and the `buf` toolchain configuration — exactly as
> they exist in source.
>
> Grounding: every service, RPC, message, enum, function, and registry entry
> below is taken verbatim from a file under `libs/proto/`. Where a name in the
> TypeScript registry disagrees with the `.proto` source, the discrepancy is
> flagged explicitly rather than silently reconciled.

---

`@oshun/proto` serves two roles simultaneously. First, it is a schema
repository: all 28 `.proto` files describing every gRPC surface in the platform
live under `libs/proto/src/`, organized one directory per domain. Second, it is
a runtime helper layer: a small TypeScript surface (`loader.ts`, `services.ts`,
`index.ts`) that loads those schemas at startup, exposes typed registries of
path keys and service names, and centralizes the channel options and credentials
every gRPC client needs.

This document is structured to match how an engineer uses the library. §1–§3
cover the package shape, source layout, and proto conventions. §4–§5 cover the
TypeScript API (loader functions and channel helpers). §6–§12 are the
authoritative RPC catalog — organized by domain group — derived directly from
the `.proto` source files. §13 documents known discrepancies between the
TypeScript registries and the `.proto` source so consumers know which artifact
to trust. §14–§18 cover the Buf toolchain, tests, and the public API surface.
§19 is the integration-point summary showing which domain owns which schema
area.

---

## 1. Package Overview

`@oshun/proto` (`package.json` `name`, `version` `0.1.0`, `private: true`) is an
Nx library at `libs/proto/`. It is `"type": "module"` (pure ESM). It builds with
`@nx/js:tsc` to `dist/libs/proto`, with `main` `libs/proto/src/index.ts`.

The package serves two roles:

1. **Schema home** — it owns every `.proto` file describing an Oshun gRPC
   surface. Twenty-eight `.proto` files live under `libs/proto/src/`, organized
   into one directory per service domain.
2. **Runtime helper layer** — a small TypeScript surface (`loader.ts`,
   `services.ts`, `index.ts`) that loads `.proto` files at runtime via
   `@grpc/proto-loader`, exposes typed path/name/metadata registries, and
   centralizes gRPC channel options and credential construction.

`project.json` tags the library `scope:shared`, `layer:contracts`.

### 1.1 Build Asset Handling

The Nx `build` target (`@nx/js:tsc`) declares an `assets` glob that copies
`**/*.proto` from `libs/proto/src` to `protos/` in the build output. The
`package.json` `exports` map exposes the raw schema files to consumers under the
`"./protos/*": "./src/*.proto"` subpath, alongside the compiled entry point
(`"."` → `./dist/index.js` / `./dist/index.d.ts`). Proto files are therefore
both compiled artifacts' siblings and directly importable as raw schema.

### 1.2 Dependencies

From `package.json`:

| Package              | Version range | Role                                                        |
| -------------------- | ------------- | ----------------------------------------------------------- |
| `@grpc/grpc-js`      | `^1.10.1`     | Pure-JS gRPC runtime: `loadPackageDefinition`, credentials  |
| `@grpc/proto-loader` | `^0.7.10`     | Runtime `.proto` → package-definition parsing               |
| `protobufjs`         | `^7.2.6`      | Underlying protobuf reflection (transitive of proto-loader) |

`typescript` `catalog:` is a `peerDependency`. The library has **no dependency
on any other Oshun library** — it is a leaf in the dependency graph.

---

## 2. Source Layout

```
libs/proto/
├── package.json               # @oshun/proto, deps, exports map
├── project.json               # Nx targets: build, lint, test, proto:gen, proto:lint
├── tsconfig.json               # references tsconfig.lib.json + tsconfig.spec.json
├── tsconfig.lib.json           # includes src/**/*.ts + scripts/**/*.ts
├── tsconfig.spec.json          # includes src/**/*.spec.ts + vitest.config.ts
├── vitest.config.ts            # node environment, v8 coverage
├── buf.work.yaml               # buf workspace: directories = [src]
├── buf.gen.yaml                # buf codegen: ts-proto, Go, Go-gRPC, JSON Schema
├── generated/
│   └── buf-image.json          # serialized FileDescriptorSet (buf image, 28 files)
├── scripts/
│   └── generate.ts             # pbjs/pbts static-module type generation script
└── src/
    ├── index.ts               # public API re-exports
    ├── loader.ts              # proto loader + PROTO_PATHS registry
    ├── services.ts            # SERVICE_NAMES, channel options, getServiceMetadata
    ├── proto.spec.ts          # Vitest suite for loader + registries
    ├── buf.yaml               # SINGLE buf module config for the whole src/ tree
    │
    ├── common/types.proto              # oshun.common — shared scalar types
    ├── shared/common.proto             # oshun.shared.common — substrate enums
    ├── shared/evidence.proto           # oshun.shared.evidence — grounded answers
    ├── shared/memory.proto             # oshun.shared.memory — continuity/memory
    ├── shared/persona_policy.proto     # oshun.shared.persona — Lilith policy
    ├── shared/generation_control.proto # oshun.shared.generation — Isis control
    ├── auth/auth.proto                 # oshun.auth
    ├── ai/ai.proto                     # oshun.ai
    ├── agent/agent.proto               # oshun.agent
    ├── asset/asset.proto               # oshun.asset
    ├── collaboration/collaboration.proto # oshun.collaboration
    ├── project/project.proto           # oshun.project
    ├── user/user.proto                 # oshun.user
    ├── isis/isis.proto                 # oshun.isis
    ├── sophia/sophia.proto             # oshun.sophia
    ├── hathor/hathor.proto             # oshun.hathor
    ├── concordia/concordia.proto       # oshun.concordia
    ├── generation3d/generation3d.proto # oshun.generation3d
    ├── rendering/rendering.proto       # oshun.rendering
    ├── splatting/gaussian_splatting.proto # oshun.splatting
    ├── procedural/procedural.proto     # oshun.procedural
    ├── pipeline/autonomous_pipeline.proto # oshun.pipeline
    ├── bridge/blender.proto            # oshun.bridge.blender
    ├── bridge/godot.proto              # oshun.bridge.godot
    ├── bridge/unreal.proto             # oshun.bridge.unreal
    ├── health/health.proto             # oshun.health
    ├── loadbalancing/loadbalancing.proto # oshun.loadbalancing
    ├── reflection/reflection.proto     # oshun.reflection
    └── oshun/v2/persistent_economy/economy.proto # oshun.v2.persistent_economy
```

> **Note on `buf.yaml` placement.** There is exactly one `buf.yaml`, at
> `libs/proto/src/buf.yaml`. It is a single buf module that covers the entire
> `src/` subtree — there are **no** per-domain `buf.yaml` files. `buf.work.yaml`
> at the library root points its `directories` list at `src`, so the module root
> is `src/`.

---

## 3. Proto File Conventions

Every `.proto` in the library follows a consistent set of structural
conventions. Understanding these conventions upfront makes it easier to read any
schema file without surprises about naming, imports, or enum zero values.

Every `.proto` in the library is `syntax = "proto3"`. Conventions observed
across all files:

- **Package naming.** `oshun.<domain>` (e.g. `oshun.ai`, `oshun.isis`). The
  shared-substrate files use a two-level suffix: `oshun.shared.common`,
  `oshun.shared.evidence`, `oshun.shared.memory`, `oshun.shared.persona`,
  `oshun.shared.generation`. The bridge files use `oshun.bridge.blender`,
  `oshun.bridge.godot`, `oshun.bridge.unreal`. The V2 game file uses
  `oshun.v2.persistent_economy`. Packages do **not** carry a `.v1` suffix —
  buf's `PACKAGE_VERSION_SUFFIX` lint rule is explicitly disabled (§9.2).
- **`go_package` option.** Every file declares
  `option go_package = "github.com/oshun/proto/<path>"` — e.g.
  `github.com/oshun/proto/ai`, `github.com/oshun/proto/shared/evidence`,
  `github.com/oshun/proto/v2/persistent_economy`.
- **No `java_package` option.** Despite what older revisions of this document
  claimed, no `.proto` file declares `java_package`.
- **Imports.** Files import `google/protobuf/timestamp.proto` for timestamps,
  `google/protobuf/struct.proto` where free-form structured payloads are needed
  (nine files: `agent`, `collaboration`, the three bridges, `rendering`, and the
  `shared/evidence`, `shared/memory`, `shared/generation_control` substrate
  files — `rendering.proto` declares the import but does not currently reference
  a `Struct` field), and `google/protobuf/duration.proto` (loadbalancing only).
  Domain files import `common/types.proto`; the shared-substrate service files
  additionally import `shared/common.proto`.
- **Enum zero values.** Every enum's zero value carries the `_UNSPECIFIED`
  suffix (buf `enum_zero_value_suffix` enforces this) — e.g.
  `AI_PROVIDER_UNSPECIFIED = 0`, `ISIS_JOB_STATUS_UNSPECIFIED = 0`.
- **Field naming.** `snake_case` field names. The loader sets `keepCase: true`,
  so field names are **not** camelCased at parse time (§4.1).

---

## 4. Loader API (`src/loader.ts`)

`loader.ts` is the runtime bridge between the static `.proto` files and the live
gRPC clients that domain services instantiate at startup. Rather than importing
pre-generated JavaScript stubs, services call `loadProto` (or `loadAllProtos` at
server start), get back a `GrpcObject`, and read the service constructor out of
it by its fully-qualified package path. This approach avoids committing
generated code and keeps the `.proto` files as the single source of truth at
both build time and runtime.

`loader.ts` provides runtime `.proto` loading on top of `@grpc/proto-loader` and
the `PROTO_PATHS` registry. It computes its own directory via
`fileURLToPath(import.meta.url)` (pure-ESM pattern).

### 4.1 `DEFAULT_LOADER_OPTIONS`

The shared loader configuration object is used by every `loadProto` call unless
a caller explicitly overrides it. The most consequential option is
`keepCase: true`, which means runtime field names stay `snake_case` exactly as
written in the `.proto` — they are **not** camelCased, unlike what
`buf generate` produces via ts-proto (see §14.3 for that divergence).

```typescript
export const DEFAULT_LOADER_OPTIONS: protoLoader.Options = {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true,
  includeDirs: [__dirname, path.join(__dirname, '..')],
};
```

| Option        | Value                       | Effect                                                          |
| ------------- | --------------------------- | --------------------------------------------------------------- |
| `keepCase`    | `true`                      | Field names kept as declared (`snake_case`, **not** camelCased) |
| `longs`       | `String`                    | 64-bit ints (`int64`/`uint64`) represented as JS strings        |
| `enums`       | `String`                    | Enum values surfaced as their string names                      |
| `defaults`    | `true`                      | Default values included in decoded output                       |
| `oneofs`      | `true`                      | Virtual `oneof` discriminator field included                    |
| `includeDirs` | `[__dirname, __dirname/..]` | Resolves imports like `common/types.proto` and `shared/...`     |

`keepCase: true` is verified by `proto.spec.ts`
(`DEFAULT_LOADER_OPTIONS.keepCase` toBe `true`). The two `includeDirs` entries
are the `src/` directory itself and its parent (`libs/proto/`), which is why a
domain file's `import "common/types.proto"` resolves.

### 4.2 `loadProto(protoPath, options?)`

```typescript
export async function loadProto(
  protoPath: string,
  options?: protoLoader.Options
): Promise<grpc.GrpcObject>;
```

Loads a single `.proto` file and returns the gRPC package object (the structure
gRPC service constructors are read from). Behavior:

- If `protoPath` is absolute it is used directly; otherwise it is resolved
  relative to the `src/` directory (`path.join(__dirname, protoPath)`). This is
  what lets callers pass a bare `PROTO_PATHS` value such as `'ai/ai.proto'`.
- Options are merged `{ ...DEFAULT_LOADER_OPTIONS, ...options }` — any caller
  override wins per-key.
- Delegates to `protoLoader.load(...)` then `grpc.loadPackageDefinition(...)`.
- **Asynchronous** — returns a `Promise<grpc.GrpcObject>`.

### 4.3 `loadProtos(protoPaths, options?)`

```typescript
export async function loadProtos(
  protoPaths: string[],
  options?: protoLoader.Options
): Promise<grpc.GrpcObject>;
```

Loads several `.proto` files and merges them into a single `GrpcObject`. It
iterates the array, calls `loadProto` for each, and `Object.assign`s each result
into a shared `merged` object. Because the merge is a shallow `Object.assign`
keyed by the top-level package segment (`oshun`), every file shares the `oshun`
root and later files' subpackages accrete onto it.

### 4.4 `loadAllProtos(options?)`

```typescript
export async function loadAllProtos(
  options?: protoLoader.Options
): Promise<grpc.GrpcObject>;
```

Convenience wrapper: `loadProtos(Object.values(PROTO_PATHS), options)`. Loads
every file registered in `PROTO_PATHS` (§4.6) in one call — used where a gRPC
server registers all services at startup.

### 4.5 `getProtoPath(relativePath)`

```typescript
export function getProtoPath(relativePath: string): string;
```

Joins `relativePath` onto the `src/` directory and returns the **absolute**
path. Unlike `loadProto`, this is a pure path helper — it does not check
existence or load anything.

### 4.6 `PROTO_PATHS` Registry

`PROTO_PATHS` is an `as const` object mapping a stable key to a `.proto` path
relative to `src/`. The exported type `ProtoPath` is
`(typeof PROTO_PATHS)[keyof typeof PROTO_PATHS]` — the union of the path string
literals. Complete contents:

| Key                       | Path                                        |
| ------------------------- | ------------------------------------------- |
| `common`                  | `common/types.proto`                        |
| `ai`                      | `ai/ai.proto`                               |
| `agent`                   | `agent/agent.proto`                         |
| `asset`                   | `asset/asset.proto`                         |
| `auth`                    | `auth/auth.proto`                           |
| `collaboration`           | `collaboration/collaboration.proto`         |
| `project`                 | `project/project.proto`                     |
| `user`                    | `user/user.proto`                           |
| `isis`                    | `isis/isis.proto`                           |
| `sophia`                  | `sophia/sophia.proto`                       |
| `hathor`                  | `hathor/hathor.proto`                       |
| `concordia`               | `concordia/concordia.proto`                 |
| `persistentEconomy`       | `oshun/v2/persistent_economy/economy.proto` |
| `sharedCommon`            | `shared/common.proto`                       |
| `sharedEvidence`          | `shared/evidence.proto`                     |
| `sharedMemory`            | `shared/memory.proto`                       |
| `sharedPersonaPolicy`     | `shared/persona_policy.proto`               |
| `sharedGenerationControl` | `shared/generation_control.proto`           |
| `generation3d`            | `generation3d/generation3d.proto`           |
| `rendering`               | `rendering/rendering.proto`                 |
| `splatting`               | `splatting/gaussian_splatting.proto`        |
| `procedural`              | `procedural/procedural.proto`               |
| `blender`                 | `bridge/blender.proto`                      |
| `godot`                   | `bridge/godot.proto`                        |
| `unreal`                  | `bridge/unreal.proto`                       |
| `health`                  | `health/health.proto`                       |
| `loadbalancing`           | `loadbalancing/loadbalancing.proto`         |
| `reflection`              | `reflection/reflection.proto`               |
| `pipeline`                | `pipeline/autonomous_pipeline.proto`        |

The source file groups these into commented sections: _Common types_, _Core
services_, _Domain services_, _Shared substrate services_, _Rendering & 3D_,
_Engine bridges_, _Infrastructure_. `proto.spec.ts` asserts most of these
key→path pairs explicitly.

---

## 5. Service Metadata & Channel Helpers (`src/services.ts`)

`services.ts` is the companion to `loader.ts`. Where `loader.ts` handles parsing
schemas from disk, `services.ts` centralizes everything needed to construct and
configure a gRPC channel: the registry of fully-qualified service names, the
shared channel options (keepalive, message-size limits), the credential factory,
and per-service metadata. A domain service imports from both modules via the
single `@oshun/proto` entry point.

`services.ts` exposes the `SERVICE_NAMES` registry, the
`DEFAULT_CHANNEL_OPTIONS` constant, the `createCredentials` helper, the
`ServiceMetadata` interface, and the `getServiceMetadata` lookup.

### 5.1 `SERVICE_NAMES` Registry

`SERVICE_NAMES` is an `as const` object mapping a registry key to a
fully-qualified gRPC service name. `ServiceName` is the union of those values.
These strings are used when constructing gRPC clients and when calling
`getServiceMetadata`. Note that two entries — `Procedural` and `Reflection` — do
not match their actual `.proto`-declared service names; see §13 for the full
discrepancy ledger.

Complete contents, grouped as in the source:

**Core services**

| Key             | Fully-qualified name                       |
| --------------- | ------------------------------------------ |
| `AI`            | `oshun.ai.AIService`                       |
| `Agent`         | `oshun.agent.AgentService`                 |
| `Asset`         | `oshun.asset.AssetService`                 |
| `Auth`          | `oshun.auth.AuthService`                   |
| `Collaboration` | `oshun.collaboration.CollaborationService` |
| `Project`       | `oshun.project.ProjectService`             |
| `User`          | `oshun.user.UserService`                   |

**Isis domain (Generative Factory)**

| Key            | Fully-qualified name             |
| -------------- | -------------------------------- |
| `IsisJob`      | `oshun.isis.IsisJobService`      |
| `IsisWorkflow` | `oshun.isis.IsisWorkflowService` |
| `IsisOutput`   | `oshun.isis.IsisOutputService`   |
| `IsisModel`    | `oshun.isis.IsisModelService`    |

**Sophia domain (Knowledge Engine)**

| Key                    | Fully-qualified name                       |
| ---------------------- | ------------------------------------------ |
| `SophiaSearch`         | `oshun.sophia.SophiaSearchService`         |
| `SophiaDocument`       | `oshun.sophia.SophiaDocumentService`       |
| `SophiaCitation`       | `oshun.sophia.SophiaCitationService`       |
| `SophiaKnowledgeGraph` | `oshun.sophia.SophiaKnowledgeGraphService` |
| `SophiaIndex`          | `oshun.sophia.SophiaIndexService`          |

**OSHUN shared substrate services**

| Key                       | Fully-qualified name                                    |
| ------------------------- | ------------------------------------------------------- |
| `SharedEvidence`          | `oshun.shared.evidence.OshunEvidenceService`            |
| `SharedMemory`            | `oshun.shared.memory.OshunMemoryService`                |
| `SharedPersonaPolicy`     | `oshun.shared.persona.OshunPersonaPolicyService`        |
| `SharedGenerationControl` | `oshun.shared.generation.OshunGenerationControlService` |

**Concordia domain (Cooperative Mediation & Negotiation)**

| Key                    | Fully-qualified name                          |
| ---------------------- | --------------------------------------------- |
| `ConcordiaSession`     | `oshun.concordia.ConcordiaSessionService`     |
| `ConcordiaNegotiation` | `oshun.concordia.ConcordiaNegotiationService` |
| `ConcordiaSearch`      | `oshun.concordia.ConcordiaSearchService`      |

**Hathor domain (Worldbuilding)**

| Key                | Fully-qualified name                   |
| ------------------ | -------------------------------------- |
| `HathorWorld`      | `oshun.hathor.HathorWorldService`      |
| `HathorFaction`    | `oshun.hathor.HathorFactionService`    |
| `HathorCharacter`  | `oshun.hathor.HathorCharacterService`  |
| `HathorLocation`   | `oshun.hathor.HathorLocationService`   |
| `HathorTimeline`   | `oshun.hathor.HathorTimelineService`   |
| `HathorNarrative`  | `oshun.hathor.HathorNarrativeService`  |
| `HathorSimulation` | `oshun.hathor.HathorSimulationService` |

**V2 game services**

| Key                   | Fully-qualified name                      |
| --------------------- | ----------------------------------------- |
| `V2PersistentEconomy` | `oshun.v2.persistent_economy.Economy`     |
| `V2NPCSchedule`       | `oshun.v2.persistent_economy.NPCSchedule` |
| `V2CrimeRate`         | `oshun.v2.persistent_economy.CrimeRate`   |

**Rendering & 3D**

| Key                 | Fully-qualified name                           |
| ------------------- | ---------------------------------------------- |
| `Generation3D`      | `oshun.generation3d.Generation3DService`       |
| `Rendering`         | `oshun.rendering.RenderingService`             |
| `GaussianSplatting` | `oshun.splatting.GaussianSplattingService`     |
| `Procedural`        | `oshun.procedural.ProceduralGenerationService` |

**Engine bridges**

| Key             | Fully-qualified name                        |
| --------------- | ------------------------------------------- |
| `BlenderBridge` | `oshun.bridge.blender.BlenderBridgeService` |
| `GodotBridge`   | `oshun.bridge.godot.GodotBridgeService`     |
| `UnrealBridge`  | `oshun.bridge.unreal.UnrealBridgeService`   |

**Infrastructure**

| Key             | Fully-qualified name                       |
| --------------- | ------------------------------------------ |
| `Health`        | `oshun.health.HealthService`               |
| `LoadBalancing` | `oshun.loadbalancing.LoadBalancingService` |
| `Reflection`    | `oshun.reflection.ReflectionService`       |
| `Pipeline`      | `oshun.pipeline.AutonomousPipelineService` |

> **Two registry entries disagree with the `.proto` source — do not treat these
> as authoritative service names:**
>
> - `SERVICE_NAMES.Procedural` is
>   `oshun.procedural.ProceduralGenerationService`, but
>   `procedural/procedural.proto` declares `service ProceduralGenService`. The
>   wire-correct fully-qualified name is
>   `oshun.procedural.ProceduralGenService`.
> - `SERVICE_NAMES.Reflection` is `oshun.reflection.ReflectionService`, but
>   `reflection/reflection.proto` declares `service ServerReflectionService`.
>   The wire-correct name is `oshun.reflection.ServerReflectionService`.
>
> See §13 for the full discrepancy ledger.

### 5.2 `DEFAULT_CHANNEL_OPTIONS`

Every gRPC client created by a domain service should use these channel options.
The keepalive settings prevent idle HTTP/2 connections from being silently
dropped by load balancers, and the 50 MB message-size limits accommodate the
largest binary payloads in the system — raw image frames for Gaussian Splatting
capture, viewport screenshots from the engine bridges, and inline document
content for Sophia ingestion.

```typescript
export const DEFAULT_CHANNEL_OPTIONS: grpc.ChannelOptions = {
  'grpc.keepalive_time_ms': 30000,
  'grpc.keepalive_timeout_ms': 10000,
  'grpc.keepalive_permit_without_calls': 1,
  'grpc.http2.min_time_between_pings_ms': 10000,
  'grpc.http2.max_pings_without_data': 0,
  'grpc.max_receive_message_length': 50 * 1024 * 1024,
  'grpc.max_send_message_length': 50 * 1024 * 1024,
};
```

| Channel option                         | Value              | Purpose                                        |
| -------------------------------------- | ------------------ | ---------------------------------------------- |
| `grpc.keepalive_time_ms`               | `30000`            | Send a keepalive ping every 30 s               |
| `grpc.keepalive_timeout_ms`            | `10000`            | Wait 10 s for the keepalive ack before failing |
| `grpc.keepalive_permit_without_calls`  | `1`                | Allow keepalive pings even with no active RPC  |
| `grpc.http2.min_time_between_pings_ms` | `10000`            | Minimum 10 s spacing between HTTP/2 pings      |
| `grpc.http2.max_pings_without_data`    | `0`                | No cap on pings sent without data frames       |
| `grpc.max_receive_message_length`      | `52428800` (50 MB) | Max inbound message size                       |
| `grpc.max_send_message_length`         | `52428800` (50 MB) | Max outbound message size                      |

The 50 MB limits and the two keepalive durations are asserted by
`proto.spec.ts`. The 50 MB ceiling accommodates large binary payloads carried
in-message — e.g. captured frame bytes on `splatting`'s `UploadFrames`, viewport
bytes on bridge captures, and inline document content on Sophia ingestion.

### 5.3 `createCredentials(...)`

```typescript
export function createCredentials(
  secure: boolean,
  rootCerts?: Buffer,
  privateKey?: Buffer,
  certChain?: Buffer
): grpc.ChannelCredentials;
```

Centralized channel-credential factory. Behavior:

- It dynamically `require('@grpc/grpc-js')` into a local `grpcLib` binding — an
  explicit accommodation for ESM/CJS interop, marked with an
  `eslint-disable-next-line @typescript-eslint/no-require-imports`.
- If `secure` is `false` → `grpcLib.credentials.createInsecure()`.
- If `secure` is `true` **and** both `privateKey` and `certChain` are supplied →
  `grpcLib.credentials.createSsl(rootCerts, privateKey, certChain)` (mutual TLS
  with a client certificate).
- If `secure` is `true` with no client key/chain →
  `grpcLib.credentials.createSsl(rootCerts)` (server-authenticated TLS;
  `rootCerts` may itself be `undefined`, in which case the system trust store is
  used).

### 5.4 `ServiceMetadata` Interface

```typescript
export interface ServiceMetadata {
  name: ServiceName; // fully-qualified gRPC service name
  protoPath: string; // .proto path relative to src/
  package: string; // proto package (e.g. 'oshun.ai')
  methods: string[]; // RPC method names
}
```

### 5.5 `getServiceMetadata(serviceName)`

```typescript
export function getServiceMetadata(
  serviceName: ServiceName
): ServiceMetadata | undefined;
```

Returns the `ServiceMetadata` for a service, or `undefined` if the name is not
in the internal table. The implementation builds a
`Record<ServiceName, ServiceMetadata>` literal keyed by every `SERVICE_NAMES`
value and indexes into it.

> **The `methods` arrays in this table are a hand-maintained summary and have
> drifted from the `.proto` sources.** They are accurate for some services and
> stale for others. Examples of drift confirmed against source:
>
> - `SERVICE_NAMES.AI` metadata lists
>   `GenerateText, StreamGenerateText, GenerateImage, GenerateAudio, Generate3DModel, GenerateEmbeddings`
>   — but `ai.proto`'s `AIService` actually defines 26 RPCs (§6.3), and never
>   defines an RPC named `GenerateAudio` returning a result directly nor a bare
>   `Generate3DModel` matching that signature list.
> - `SERVICE_NAMES.Agent` metadata lists
>   `CreateAgent, GetAgent, UpdateAgent, DeleteAgent, ListAgents, RunAgent` —
>   but `agent.proto`'s `AgentService` has no `CreateAgent`, `DeleteAgent`, or
>   `RunAgent`; it has `RegisterAgent`, `DeregisterAgent`, `AssignTask`, etc.
>   (§7.1).
> - `SERVICE_NAMES.Reflection` metadata lists a single method
>   `ServerReflectionInfo`, which **does** match the `.proto` RPC, but is keyed
>   under the non-existent service name `oshun.reflection.ReflectionService`.
>
> **For the authoritative RPC list of any service, use the `.proto` catalog in
> §6–§12 of this document, not the `getServiceMetadata` `methods` array.** The
> sections below enumerate every RPC directly from source.

---

## 6. Common & Core Service Definitions

Sections §6–§12 are the authoritative RPC catalog for the entire library. Every
service, RPC, request type, response type, key message, and enum listed here is
taken directly from the `.proto` source files under `libs/proto/src/`. Where the
TypeScript registry in `services.ts` disagrees with a `.proto` declaration, the
`.proto` is correct and the discrepancy is noted in §13.

Each section introduces the service group with context on what problem it
solves, followed by the complete RPC table and key message/enum descriptions.
The streaming kind notation used throughout is:

- **unary** — `rpc M(Req) returns (Resp)`
- **server-stream** — `rpc M(Req) returns (stream Resp)`
- **client-stream** — `rpc M(stream Req) returns (Resp)`
- **bidi-stream** — `rpc M(stream Req) returns (stream Resp)`

This and the following sections (§7–§12) catalog every service, RPC, and message
defined in the `.proto` files. Streaming kind notation:

- **unary** — `rpc M(Req) returns (Resp)`
- **server-stream** — `rpc M(Req) returns (stream Resp)`
- **client-stream** — `rpc M(stream Req) returns (Resp)`
- **bidi-stream** — `rpc M(stream Req) returns (stream Resp)`

### 6.1 `common/types.proto` — package `oshun.common`

`common/types.proto` is the vocabulary file for the entire library. It defines
no service — only the scalar wrapper types, pagination structures, error shapes,
and health types that every domain `.proto` imports. By centralizing these, the
library guarantees that a `PaginationRequest` means the same thing in an auth
call as in a rendering call, and that errors are structured consistently across
all services.

No service; pure shared types imported by every domain `.proto`.

| Message               | Fields                                                                                                                                          |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `UUID`                | `value` (string)                                                                                                                                |
| `PaginationRequest`   | `page` (int32, 1-indexed), `limit` (int32, max 100), `sort_by` (string), `order` (`SortOrder`)                                                  |
| `PaginationMeta`      | `page`, `limit` (int32), `total` (int64), `total_pages` (int32), `has_next`, `has_previous` (bool)                                              |
| `Error`               | `code` (string), `message` (string), `details` (repeated `FieldError`), `request_id` (string)                                                   |
| `FieldError`          | `field`, `message`, `code` (string) — field-level validation error                                                                              |
| `Empty`               | (no fields) — request/response for operations with no data                                                                                      |
| `SuccessResponse`     | `success` (bool), `message` (string)                                                                                                            |
| `HealthCheckRequest`  | `service` (string)                                                                                                                              |
| `HealthCheckResponse` | `status` (`HealthStatus`), `service`, `version` (string), `timestamp` (Timestamp), `uptime_seconds` (int64), `checks` (repeated `ServiceCheck`) |
| `ServiceCheck`        | `name` (string), `status` (`HealthStatus`), `response_time_ms` (int64), `error_message` (string)                                                |

Enums: `SortOrder` (`UNSPECIFIED`, `ASC`, `DESC`); `HealthStatus`
(`UNSPECIFIED`, `HEALTHY`, `DEGRADED`, `UNHEALTHY`).

`Empty`, `SuccessResponse`, `UUID`, `PaginationRequest`, `PaginationMeta`,
`Error`, and `SortOrder` are the most widely reused: most domain RPCs returning
"no payload" return `common.SuccessResponse`, every list RPC pages with
`common.PaginationRequest` / `common.PaginationMeta`, and Concordia's stream
error frames embed `oshun.common.Error`.

### 6.2 `auth/auth.proto` — `AuthService` (package `oshun.auth`)

`AuthService` handles both user-facing authentication (login, registration,
password reset) and the internal token-validation surface that other services
use. The two validation RPCs — `ValidateToken` and `GetTokenClaims` — are the
key cross-service primitives: a service interceptor can call these to
authenticate an incoming gRPC request without any shared session state or HTTP
round-trip.

18 RPCs, all unary. Token validation (`ValidateToken`, `GetTokenClaims`) is the
inter-service-auth surface; the rest are user-facing auth flows.

| RPC                       | Request                       | Response                 |
| ------------------------- | ----------------------------- | ------------------------ |
| `Login`                   | `LoginRequest`                | `AuthResponse`           |
| `Register`                | `RegisterRequest`             | `AuthResponse`           |
| `Logout`                  | `LogoutRequest`               | `common.SuccessResponse` |
| `RefreshToken`            | `RefreshTokenRequest`         | `TokenPair`              |
| `RequestPasswordReset`    | `PasswordResetRequest`        | `common.SuccessResponse` |
| `ConfirmPasswordReset`    | `PasswordResetConfirmRequest` | `common.SuccessResponse` |
| `ChangePassword`          | `ChangePasswordRequest`       | `common.SuccessResponse` |
| `VerifyEmail`             | `EmailVerificationRequest`    | `common.SuccessResponse` |
| `ResendVerificationEmail` | `common.Empty`                | `common.SuccessResponse` |
| `ValidateToken`           | `ValidateTokenRequest`        | `ValidateTokenResponse`  |
| `GetTokenClaims`          | `ValidateTokenRequest`        | `TokenClaims`            |
| `ListSessions`            | `ListSessionsRequest`         | `ListSessionsResponse`   |
| `RevokeSession`           | `RevokeSessionRequest`        | `common.SuccessResponse` |
| `RevokeAllSessions`       | `common.Empty`                | `common.SuccessResponse` |
| `ListApiKeys`             | `common.Empty`                | `ListApiKeysResponse`    |
| `CreateApiKey`            | `CreateApiKeyRequest`         | `CreateApiKeyResponse`   |
| `DeleteApiKey`            | `DeleteApiKeyRequest`         | `common.SuccessResponse` |
| `ValidateApiKey`          | `ValidateApiKeyRequest`       | `ValidateApiKeyResponse` |

Key messages: `User` (`id`, `email`, optional `username`, `first_name`,
`last_name`, `avatar_url`, `role` `UserRole`, `status` `UserStatus`,
`email_verified`, `created_at`); `TokenPair` (`access_token`, `refresh_token`,
`access_expires_at`, `refresh_expires_at`, `token_type`); `TokenClaims`
(`user_id`, `email`, `role`, repeated `permissions`, `issued_at`, `expires_at`,
`session_id`); `Session` (device/browser/os/ip/location, `is_current`,
`created_at`, `last_active_at`); `ApiKey` (`id`, `name`, `key_prefix`, repeated
`scopes`, timestamps — never carries the raw key). `CreateApiKeyResponse`
carries both the `ApiKey` and a `full_key` string (shown once). Enums:
`UserRole` (`USER`, `CREATOR`, `ADMIN`, `SUPER_ADMIN`), `UserStatus` (`PENDING`,
`ACTIVE`, `SUSPENDED`, `DELETED`).

### 6.3 `ai/ai.proto` — `AIService` (package `oshun.ai`)

`AIService` is the single cross-provider generation surface: a caller names a
provider and model, sends a prompt or media input, and gets back either a
streaming response (text, code) or a job handle to poll for completion (images,
audio, speech, 3D). This single service abstracts over Anthropic, OpenAI,
Google, Stability, ElevenLabs, Replicate, and a local provider, so domain
services don't need to implement per-provider clients.

26 RPCs spanning text/image/audio/3D/code generation, embeddings, job
management, prompt templates, usage stats, and provider info. Two are
server-streaming; the rest are unary.

| RPC                    | Request                       | Response                       | Kind          |
| ---------------------- | ----------------------------- | ------------------------------ | ------------- |
| `GenerateText`         | `GenerateTextRequest`         | `GenerateTextResponse`         | unary         |
| `StreamGenerateText`   | `GenerateTextRequest`         | `TextChunk`                    | server-stream |
| `GenerateImage`        | `GenerateImageRequest`        | `GenerateJobResponse`          | unary         |
| `GetImageResult`       | `GetGenerationResultRequest`  | `ImageResultResponse`          | unary         |
| `GenerateAudio`        | `GenerateAudioRequest`        | `GenerateJobResponse`          | unary         |
| `GenerateSpeech`       | `GenerateSpeechRequest`       | `GenerateJobResponse`          | unary         |
| `GetAudioResult`       | `GetGenerationResultRequest`  | `AudioResultResponse`          | unary         |
| `Generate3DModel`      | `Generate3DModelRequest`      | `GenerateJobResponse`          | unary         |
| `Get3DModelResult`     | `GetGenerationResultRequest`  | `Model3DResultResponse`        | unary         |
| `GenerateCode`         | `GenerateCodeRequest`         | `GenerateCodeResponse`         | unary         |
| `StreamGenerateCode`   | `GenerateCodeRequest`         | `CodeChunk`                    | server-stream |
| `GenerateEmbeddings`   | `GenerateEmbeddingsRequest`   | `EmbeddingsResponse`           | unary         |
| `SearchSimilar`        | `SearchSimilarRequest`        | `SearchSimilarResponse`        | unary         |
| `GetJob`               | `GetJobRequest`               | `JobResponse`                  | unary         |
| `ListJobs`             | `ListJobsRequest`             | `ListJobsResponse`             | unary         |
| `CancelJob`            | `CancelJobRequest`            | `common.SuccessResponse`       | unary         |
| `RetryJob`             | `RetryJobRequest`             | `JobResponse`                  | unary         |
| `ListPromptTemplates`  | `ListPromptTemplatesRequest`  | `ListPromptTemplatesResponse`  | unary         |
| `CreatePromptTemplate` | `CreatePromptTemplateRequest` | `PromptTemplateResponse`       | unary         |
| `GetPromptTemplate`    | `GetPromptTemplateRequest`    | `PromptTemplateResponse`       | unary         |
| `UpdatePromptTemplate` | `UpdatePromptTemplateRequest` | `PromptTemplateResponse`       | unary         |
| `DeletePromptTemplate` | `DeletePromptTemplateRequest` | `common.SuccessResponse`       | unary         |
| `RenderPromptTemplate` | `RenderPromptTemplateRequest` | `RenderPromptTemplateResponse` | unary         |
| `GetUsageStats`        | `GetUsageStatsRequest`        | `UsageStatsResponse`           | unary         |
| `ListProviders`        | `ListProvidersRequest`        | `ListProvidersResponse`        | unary         |
| `GetProviderStatus`    | `GetProviderStatusRequest`    | `ProviderStatusResponse`       | unary         |

Enums: `AIProvider` (`ANTHROPIC`, `OPENAI`, `GOOGLE`, `STABILITY`, `ELEVENLABS`,
`REPLICATE`, `LOCAL`); `GenerationType` (`TEXT`, `IMAGE`, `AUDIO`, `SPEECH`,
`MODEL_3D`, `CODE`, `EMBEDDING`); `JobStatus` (`PENDING`, `PROCESSING`,
`COMPLETED`, `FAILED`, `CANCELLED`); `ImageStyle` (`REALISTIC`, `ARTISTIC`,
`ANIME`, `PIXEL_ART`, `CONCEPT_ART`, `PHOTOGRAPHIC`, `DIGITAL_ART`).

Notable messages: `GenerateTextRequest` carries `prompt`, optional
`system_prompt`, optional `provider`/`model`, sampling controls (`max_tokens`,
`temperature`, `top_p`, repeated `stop_sequences`); `TextChunk` (streamed) has
`text`, `is_final`, optional `usage`, `finish_reason`; `TokenUsage`
(`prompt_tokens`, `completion_tokens`, `total_tokens`); `Generate3DModelRequest`
has a `oneof input { string prompt; string image_url }`. `GenerateJobResponse`
returns a `job_id`, `status`, `type`, optional `estimated_seconds` — the
async-job pattern: image/audio/speech/3D generation return a job handle, then
`GetImageResult` / `GetAudioResult` / `Get3DModelResult` retrieve the finished
artifact. `Job` carries the full job record; `UsageStats` aggregates
`total_requests`/`total_tokens`/`total_images`/`total_audio_seconds`/
`estimated_cost_usd` with `UsageByType` / `UsageByProvider` / `UsageTimeSeries`
breakdowns.

### 6.4 `agent/agent.proto` — see §7.1

### 6.5 `asset/asset.proto` — `AssetService` (package `oshun.asset`)

`AssetService` manages the lifecycle of binary assets across the platform: 3D
models, images, video, audio, documents, and archives. Rather than piping large
files through gRPC messages, it uses a two-phase upload pattern: `CreateAsset`
returns a pre-signed storage URL; the client uploads directly to storage; then
`CompleteUpload` records the final metadata. The `UpdateProcessingStatus` RPC is
the internal callback that the processing pipeline uses after it has generated
thumbnails and extracted metadata, decoupling the upload from the potentially
slow processing step.

23 RPCs, all unary, covering asset CRUD with pre-signed-URL upload, locking,
versioning, folders, moves, bulk operations, search, and an internal
processing-callback RPC.

| RPC                      | Request                         | Response                 |
| ------------------------ | ------------------------------- | ------------------------ |
| `CreateAsset`            | `CreateAssetRequest`            | `CreateAssetResponse`    |
| `CompleteUpload`         | `CompleteUploadRequest`         | `AssetResponse`          |
| `GetAsset`               | `GetAssetRequest`               | `AssetResponse`          |
| `UpdateAsset`            | `UpdateAssetRequest`            | `AssetResponse`          |
| `DeleteAsset`            | `DeleteAssetRequest`            | `common.SuccessResponse` |
| `ListAssets`             | `ListAssetsRequest`             | `ListAssetsResponse`     |
| `GetDownloadUrl`         | `GetDownloadUrlRequest`         | `DownloadUrlResponse`    |
| `LockAsset`              | `LockAssetRequest`              | `AssetResponse`          |
| `UnlockAsset`            | `UnlockAssetRequest`            | `AssetResponse`          |
| `ListVersions`           | `ListVersionsRequest`           | `ListVersionsResponse`   |
| `CreateVersion`          | `CreateVersionRequest`          | `CreateVersionResponse`  |
| `GetVersion`             | `GetVersionRequest`             | `VersionResponse`        |
| `RestoreVersion`         | `RestoreVersionRequest`         | `AssetResponse`          |
| `ListFolders`            | `ListFoldersRequest`            | `ListFoldersResponse`    |
| `CreateFolder`           | `CreateFolderRequest`           | `FolderResponse`         |
| `GetFolder`              | `GetFolderRequest`              | `FolderResponse`         |
| `UpdateFolder`           | `UpdateFolderRequest`           | `FolderResponse`         |
| `DeleteFolder`           | `DeleteFolderRequest`           | `common.SuccessResponse` |
| `MoveFolder`             | `MoveFolderRequest`             | `FolderResponse`         |
| `MoveAsset`              | `MoveAssetRequest`              | `AssetResponse`          |
| `BulkOperation`          | `BulkOperationRequest`          | `BulkOperationResponse`  |
| `SearchAssets`           | `SearchAssetsRequest`           | `ListAssetsResponse`     |
| `UpdateProcessingStatus` | `UpdateProcessingStatusRequest` | `common.SuccessResponse` |

`CreateAsset` is a two-phase upload: the response returns an `upload_url`,
`expires_at`, and `max_size_bytes`; the client uploads directly, then calls
`CompleteUpload`. `CreateVersion` mirrors this for new versions. `Asset` carries
type/status, size, mime, `url`, `Thumbnails` (`small`/`medium`/`large`),
`AssetMetadata` (per-type: image dims, video frame rate/codec/bitrate, 3D
vertices/faces/materials, audio channels/sample-rate, document pages), version
counters, folder/project linkage, and a `locked_by`/`locked_at` pair.
`UpdateProcessingStatus` is the internal callback the processing pipeline uses
to push status, metadata, and thumbnails back. Enums: `AssetType` (`IMAGE`,
`VIDEO`, `AUDIO`, `MODEL_3D`, `DOCUMENT`, `SCRIPT`, `FONT`, `ARCHIVE`, `OTHER`);
`AssetStatus` (`UPLOADING`, `PROCESSING`, `READY`, `ERROR`, `ARCHIVED`);
`BulkOperation` (`MOVE`, `DELETE`, `ARCHIVE`, `TAG`).

### 6.6 `collaboration/collaboration.proto` — `CollaborationService` (package `oshun.collaboration`)

`CollaborationService` enables real-time multi-user editing sessions. Its design
is anchored around `SyncDocument`, a bidirectional stream that exchanges
operational-transform frames in both directions without round-trip overhead —
the same technique used by Google Docs. The three server-streams
(`StreamPresence`, `StreamCursors`, `StreamActivity`) push peripheral state (who
is online, where cursors are, what just happened) as events rather than
requiring clients to poll.

32 RPCs. This is the only core service with a **bidirectional** stream
(`SyncDocument`) plus three server-streams.

| RPC                  | Request                     | Response                     | Kind          |
| -------------------- | --------------------------- | ---------------------------- | ------------- |
| `CreateSession`      | `CreateSessionRequest`      | `SessionResponse`            | unary         |
| `GetSession`         | `GetSessionRequest`         | `SessionResponse`            | unary         |
| `EndSession`         | `EndSessionRequest`         | `common.SuccessResponse`     | unary         |
| `ListSessions`       | `ListSessionsRequest`       | `ListSessionsResponse`       | unary         |
| `JoinSession`        | `JoinSessionRequest`        | `SessionResponse`            | unary         |
| `LeaveSession`       | `LeaveSessionRequest`       | `common.SuccessResponse`     | unary         |
| `SyncDocument`       | `DocumentUpdate`            | `DocumentUpdate`             | bidi-stream   |
| `GetDocumentState`   | `GetDocumentStateRequest`   | `DocumentStateResponse`      | unary         |
| `ApplyOperation`     | `ApplyOperationRequest`     | `ApplyOperationResponse`     | unary         |
| `UpdatePresence`     | `UpdatePresenceRequest`     | `common.SuccessResponse`     | unary         |
| `GetPresence`        | `GetPresenceRequest`        | `PresenceResponse`           | unary         |
| `StreamPresence`     | `StreamPresenceRequest`     | `PresenceUpdate`             | server-stream |
| `UpdateCursor`       | `UpdateCursorRequest`       | `common.SuccessResponse`     | unary         |
| `StreamCursors`      | `StreamCursorsRequest`      | `CursorUpdate`               | server-stream |
| `AcquireLock`        | `AcquireLockRequest`        | `LockResponse`               | unary         |
| `ReleaseLock`        | `ReleaseLockRequest`        | `common.SuccessResponse`     | unary         |
| `GetLocks`           | `GetLocksRequest`           | `GetLocksResponse`           | unary         |
| `ForceReleaseLock`   | `ForceReleaseLockRequest`   | `common.SuccessResponse`     | unary         |
| `CreateThread`       | `CreateThreadRequest`       | `ThreadResponse`             | unary         |
| `GetThread`          | `GetThreadRequest`          | `ThreadResponse`             | unary         |
| `ResolveThread`      | `ResolveThreadRequest`      | `ThreadResponse`             | unary         |
| `ListThreads`        | `ListThreadsRequest`        | `ListThreadsResponse`        | unary         |
| `AddComment`         | `AddCommentRequest`         | `CommentResponse`            | unary         |
| `UpdateComment`      | `UpdateCommentRequest`      | `CommentResponse`            | unary         |
| `DeleteComment`      | `DeleteCommentRequest`      | `common.SuccessResponse`     | unary         |
| `RequestReview`      | `RequestReviewRequest`      | `ReviewResponse`             | unary         |
| `SubmitReview`       | `SubmitReviewRequest`       | `ReviewResponse`             | unary         |
| `GetReview`          | `GetReviewRequest`          | `ReviewResponse`             | unary         |
| `ListReviews`        | `ListReviewsRequest`        | `ListReviewsResponse`        | unary         |
| `LogActivity`        | `LogActivityRequest`        | `common.SuccessResponse`     | unary         |
| `StreamActivity`     | `StreamActivityRequest`     | `Activity`                   | server-stream |
| `GetActivityHistory` | `GetActivityHistoryRequest` | `GetActivityHistoryResponse` | unary         |

`SyncDocument` carries `DocumentUpdate` frames both directions — `session_id`,
`user_id`, `version` (int64), repeated `Operation`, `timestamp`. `Operation` has
`type`, `path`, a `google.protobuf.Struct` `value`, and optional
`position`/`length` — the operational-transform unit. `Participant` carries
`PresenceStatus`, optional `CursorPosition` (path + offset + anchor + color) and
`ViewportPosition` (scroll x/y + zoom). Enums: `SessionType` (`EDITING`,
`VIEWING`, `REVIEW`, `PRESENTATION`); `SessionStatus` (`ACTIVE`, `PAUSED`,
`ENDED`); `PresenceStatus` (`ONLINE`, `AWAY`, `BUSY`, `OFFLINE`); `LockType`
(`EXCLUSIVE`, `SHARED`); `ReviewStatus` (`PENDING`, `IN_PROGRESS`, `APPROVED`,
`CHANGES_REQUESTED`, `REJECTED`); `ActivityType` (`JOIN`, `LEAVE`, `EDIT`,
`COMMENT`, `LOCK`, `UNLOCK`, `REVIEW`, `APPROVE`, `REJECT`).

### 6.7 `project/project.proto` — `ProjectService` (package `oshun.project`)

`ProjectService` is the shared project container that creative services build on
top of. It provides the membership model (`ProjectRole`: owner, admin, editor,
viewer) and the two internal authorization RPCs — `CheckAccess` and
`GetUserRole` — that other services call to verify permissions without
duplicating membership logic. Any service that gates an action on project
membership makes a unary call here rather than querying a shared database.

19 RPCs, all unary: project CRUD (including slug lookup), membership, comments,
activity, and two internal authorization-check RPCs.

| RPC                | Request                   | Response                 |
| ------------------ | ------------------------- | ------------------------ |
| `CreateProject`    | `CreateProjectRequest`    | `ProjectResponse`        |
| `GetProject`       | `GetProjectRequest`       | `ProjectResponse`        |
| `GetProjectBySlug` | `GetProjectBySlugRequest` | `ProjectResponse`        |
| `UpdateProject`    | `UpdateProjectRequest`    | `ProjectResponse`        |
| `DeleteProject`    | `DeleteProjectRequest`    | `common.SuccessResponse` |
| `ListProjects`     | `ListProjectsRequest`     | `ListProjectsResponse`   |
| `ListMembers`      | `ListMembersRequest`      | `ListMembersResponse`    |
| `AddMember`        | `AddMemberRequest`        | `MemberResponse`         |
| `UpdateMember`     | `UpdateMemberRequest`     | `MemberResponse`         |
| `RemoveMember`     | `RemoveMemberRequest`     | `common.SuccessResponse` |
| `ListComments`     | `ListCommentsRequest`     | `ListCommentsResponse`   |
| `CreateComment`    | `CreateCommentRequest`    | `CommentResponse`        |
| `UpdateComment`    | `UpdateCommentRequest`    | `CommentResponse`        |
| `DeleteComment`    | `DeleteCommentRequest`    | `common.SuccessResponse` |
| `ResolveComment`   | `ResolveCommentRequest`   | `CommentResponse`        |
| `ListActivity`     | `ListActivityRequest`     | `ListActivityResponse`   |
| `LogActivity`      | `LogActivityRequest`      | `common.SuccessResponse` |
| `CheckAccess`      | `CheckAccessRequest`      | `CheckAccessResponse`    |
| `GetUserRole`      | `GetUserRoleRequest`      | `GetUserRoleResponse`    |

`Project` carries `name`/`slug`, type/status/visibility, thumbnail/cover URLs,
`ProjectSettings` (`default_branch`, versioning/comments/time-tracking flags,
`frame_rate`, `Resolution`, `aspect_ratio`, `color_space`), owner, member/asset
counts, `storage_used_bytes`. `CheckAccess` and `GetUserRole` are the internal
authz surface: `CheckAccessResponse` returns `allowed` + optional `reason`;
`GetUserRoleResponse` returns `is_member`, optional `role`, repeated
`permissions`. `DeleteProject` requires a `confirmation` string. Enums:
`ProjectType` (`FILM`, `GAME`, `ANIMATION`, `COMMERCIAL`, `MUSIC_VIDEO`,
`OTHER`); `ProjectStatus` (`DRAFT`, `ACTIVE`, `ON_HOLD`, `COMPLETED`,
`ARCHIVED`); `ProjectVisibility` (`PRIVATE`, `TEAM`, `ORGANIZATION`, `PUBLIC`);
`ProjectRole` (`OWNER`, `ADMIN`, `EDITOR`, `VIEWER`).

### 6.8 `user/user.proto` — `UserService` (package `oshun.user`)

`UserService` owns user profile and identity data. The most important
cross-service primitive here is `BatchGetUsers`: it accepts repeated `UUID`s and
returns the corresponding `User` records in a single call, which is how any
service that lists items with owner/creator information hydrates the user
details without N individual lookups. `UserProfile` is the public projection (no
email, adds social counts) used wherever a user's identity is displayed to other
users.

16 RPCs, all unary: profile operations, internal lookups (including
`BatchGetUsers`), preferences, stats, activity, and notifications.

| RPC                        | Request                       | Response                    |
| -------------------------- | ----------------------------- | --------------------------- |
| `GetUser`                  | `GetUserRequest`              | `UserResponse`              |
| `GetUserByEmail`           | `GetUserByEmailRequest`       | `UserResponse`              |
| `GetUserProfile`           | `GetUserRequest`              | `UserProfileResponse`       |
| `UpdateUser`               | `UpdateUserRequest`           | `UserResponse`              |
| `DeleteUser`               | `DeleteUserRequest`           | `common.SuccessResponse`    |
| `ListUsers`                | `ListUsersRequest`            | `ListUsersResponse`         |
| `BatchGetUsers`            | `BatchGetUsersRequest`        | `BatchGetUsersResponse`     |
| `GetPreferences`           | `GetUserRequest`              | `UserPreferencesResponse`   |
| `UpdatePreferences`        | `UpdatePreferencesRequest`    | `UserPreferencesResponse`   |
| `GetUserStats`             | `GetUserRequest`              | `UserStatsResponse`         |
| `ListActivity`             | `ListActivityRequest`         | `ListActivityResponse`      |
| `LogActivity`              | `LogActivityRequest`          | `common.SuccessResponse`    |
| `ListNotifications`        | `ListNotificationsRequest`    | `ListNotificationsResponse` |
| `MarkNotificationRead`     | `MarkNotificationReadRequest` | `common.SuccessResponse`    |
| `MarkAllNotificationsRead` | `GetUserRequest`              | `common.SuccessResponse`    |
| `SendNotification`         | `SendNotificationRequest`     | `common.SuccessResponse`    |

`User` is the full record; `UserProfile` is the public projection (no email,
adds project/follower/following counts). `UserPreferences` carries
`ThemePreference`, locale fields, three notification-toggle booleans, a
`NotificationSettings` block (per-event toggles), and `EditorSettings`
(`auto_save`, `auto_save_interval_seconds`, `vim_mode`, `font_size`,
`font_family`, `show_line_numbers`). `BatchGetUsers` takes repeated `UUID` and
returns repeated `User` — the cross-service user-hydration RPC. Enums:
`UserRole` and `UserStatus` (same value sets as `auth.proto`); `ThemePreference`
(`LIGHT`, `DARK`, `SYSTEM`).

---

## 7. Agent & Pipeline Service Definitions

This section covers the two services that model autonomous work orchestration.
`AgentService` handles the lifecycle of individual compute agents — registering
them, routing tasks to them, streaming their output, and grouping them into
autoscaling pools. `AutonomousPipelineService` operates at a higher level of
abstraction, modeling an entire game or movie production as a project with
phases, quality gates, and agent assignments.

### 7.1 `agent/agent.proto` — `AgentService` (package `oshun.agent`)

28 RPCs covering agent registration/lifecycle, task management, task I/O
streaming, agent pools with autoscaling, inter-agent messaging, and metrics. Two
server-streams (`StreamTaskOutput`, `StreamMessages`); the rest unary. Imports
`google/protobuf/struct.proto` for free-form task input/output and message
payloads.

| RPC                   | Request                      | Response                 | Kind          |
| --------------------- | ---------------------------- | ------------------------ | ------------- |
| `RegisterAgent`       | `RegisterAgentRequest`       | `AgentResponse`          | unary         |
| `GetAgent`            | `GetAgentRequest`            | `AgentResponse`          | unary         |
| `UpdateAgent`         | `UpdateAgentRequest`         | `AgentResponse`          | unary         |
| `DeregisterAgent`     | `DeregisterAgentRequest`     | `common.SuccessResponse` | unary         |
| `ListAgents`          | `ListAgentsRequest`          | `ListAgentsResponse`     | unary         |
| `StartAgent`          | `StartAgentRequest`          | `AgentResponse`          | unary         |
| `StopAgent`           | `StopAgentRequest`           | `AgentResponse`          | unary         |
| `RestartAgent`        | `RestartAgentRequest`        | `AgentResponse`          | unary         |
| `Heartbeat`           | `HeartbeatRequest`           | `HeartbeatResponse`      | unary         |
| `AssignTask`          | `AssignTaskRequest`          | `TaskResponse`           | unary         |
| `GetTask`             | `GetTaskRequest`             | `TaskResponse`           | unary         |
| `UpdateTaskStatus`    | `UpdateTaskStatusRequest`    | `TaskResponse`           | unary         |
| `CancelTask`          | `CancelTaskRequest`          | `TaskResponse`           | unary         |
| `ListTasks`           | `ListTasksRequest`           | `ListTasksResponse`      | unary         |
| `StreamTaskOutput`    | `StreamTaskOutputRequest`    | `TaskOutput`             | server-stream |
| `SendTaskInput`       | `SendTaskInputRequest`       | `common.SuccessResponse` | unary         |
| `CreatePool`          | `CreatePoolRequest`          | `PoolResponse`           | unary         |
| `GetPool`             | `GetPoolRequest`             | `PoolResponse`           | unary         |
| `UpdatePool`          | `UpdatePoolRequest`          | `PoolResponse`           | unary         |
| `DeletePool`          | `DeletePoolRequest`          | `common.SuccessResponse` | unary         |
| `ListPools`           | `ListPoolsRequest`           | `ListPoolsResponse`      | unary         |
| `AddAgentToPool`      | `AddAgentToPoolRequest`      | `PoolResponse`           | unary         |
| `RemoveAgentFromPool` | `RemoveAgentFromPoolRequest` | `PoolResponse`           | unary         |
| `SendMessage`         | `SendMessageRequest`         | `MessageResponse`        | unary         |
| `StreamMessages`      | `StreamMessagesRequest`      | `AgentMessage`           | server-stream |
| `BroadcastMessage`    | `BroadcastMessageRequest`    | `BroadcastResponse`      | unary         |
| `GetAgentMetrics`     | `GetAgentMetricsRequest`     | `AgentMetricsResponse`   | unary         |
| `GetPoolMetrics`      | `GetPoolMetricsRequest`      | `PoolMetricsResponse`    | unary         |

`Agent` carries type/status, version, repeated `capabilities`, `AgentConfig`
(`max_concurrent_tasks`, `task_timeout_seconds`, `heartbeat_interval_seconds`,
allowed task types, env map), `AgentResources` (`cpu_cores`, `memory_bytes`,
`disk_bytes`, optional GPU count/memory), optional pool/task linkage. `Task`
carries `google.protobuf.Struct` `input`/`output`, `TaskStatus`, `TaskPriority`,
parent/child task IDs, `required_capabilities`, retry counters.
`HeartbeatRequest` reports `AgentResourceUsage` and current task progress;
`HeartbeatResponse` returns repeated `AgentCommand` (a `type` + `Struct`
payload) — the control channel back to the agent. `TaskOutput` (streamed)
carries a `stream` name + raw `bytes data`; `SendTaskInput` pushes raw `bytes`.
`Pool` + `PoolConfig` model autoscaling (`min_agents`, `max_agents`,
`target_utilization_percent`, scale-up/down thresholds, `cooldown_seconds`).
Enums: `AgentType` (`WORKER`, `COORDINATOR`, `SUPERVISOR`, `SPECIALIST`);
`AgentStatus` (`REGISTERING`, `IDLE`, `BUSY`, `PAUSED`, `ERROR`, `OFFLINE`,
`TERMINATING`); `TaskStatus` (`PENDING`, `ASSIGNED`, `RUNNING`, `WAITING`,
`COMPLETED`, `FAILED`, `CANCELLED`, `TIMEOUT`); `TaskPriority` (`LOW`, `NORMAL`,
`HIGH`, `CRITICAL`); `ScalingPolicy` (`FIXED`, `AUTO`, `MANUAL`).

### 7.2 `pipeline/autonomous_pipeline.proto` — `AutonomousPipelineService` (package `oshun.pipeline`)

`AutonomousPipelineService` is the orchestration surface for fully autonomous
game and movie production. A project starts from nothing more than a free-text
prompt and a `ProjectType`; the service then drives it through up to 20 named
phases (concept, story, asset creation, VFX, localization, and more), tracking
quality gates at each transition and routing work to specialized agents. The two
server-streaming RPCs — `StreamUpdates` and `StreamAgentActivity` — let a
dashboard receive live progress without polling.

43 RPCs. It models end-to-end autonomous game/movie creation: project lifecycle,
phase execution, task management, progress streaming, quality gates, agent
management, asset tracking, metrics, and templates. Two server-streams
(`StreamUpdates`, `StreamAgentActivity`); the rest unary. RPC roster by section:

- **Project lifecycle (7):** `CreateProject` → `ProjectResponse`, `GetProject`,
  `ListProjects` → `ListProjectsResponse`, `UpdateProject`, `CancelProject` →
  `common.SuccessResponse`, `ArchiveProject` → `common.SuccessResponse`,
  `CloneProject` → `ProjectResponse`.
- **Phase execution (7):** `ExecutePhase` → `PhaseResponse`, `GetPhase`,
  `ListPhases` → `ListPhasesResponse`, `SkipPhase` → `common.SuccessResponse`,
  `RetryPhase` → `PhaseResponse`, `PausePhase` → `common.SuccessResponse`,
  `ResumePhase` → `PhaseResponse`.
- **Task management (7):** `GetTask` → `TaskResponse`, `ListTasks` →
  `ListTasksResponse`, `ExecuteTask`, `RetryTask`, `SkipTask` →
  `common.SuccessResponse`, `AddTask`, `UpdateTaskPriority` (the last three
  `→ TaskResponse` except `SkipTask`).
- **Progress & streaming (4):** `GetProgress` → `ProgressResponse`,
  `StreamUpdates` → `stream PipelineUpdate`, `StreamAgentActivity` →
  `stream AgentActivity`, `GetTimeline` → `TimelineResponse`.
- **Quality gates (4):** `GetQualityGate` → `QualityGateResponse`,
  `ListQualityGates` → `ListQualityGatesResponse`, `OverrideQualityGate` →
  `common.SuccessResponse`, `RunQualityCheck` → `QualityCheckResponse`.
- **Agent management (4):** `GetAgentStatus` → `AgentStatusResponse`,
  `ListAgents` → `ListAgentsResponse`, `AssignAgent` → `common.SuccessResponse`,
  `GetAgentOutput` → `AgentOutputResponse`.
- **Asset tracking (3):** `ListGeneratedAssets` → `ListGeneratedAssetsResponse`,
  `GetAssetDependencies` → `AssetDependenciesResponse`, `ExportAssets` →
  `ExportAssetsResponse`.
- **Metrics & analytics (3):** `GetMetrics` → `MetricsResponse`,
  `GetCostEstimate` → `CostEstimateResponse`, `GetResourceUsage` →
  `ResourceUsageResponse`.
- **Templates & presets (4):** `ListProjectTemplates` →
  `ListProjectTemplatesResponse`, `GetProjectTemplate` →
  `ProjectTemplateResponse`, `CreateFromTemplate` → `ProjectResponse`,
  `SaveAsTemplate` → `ProjectTemplateResponse`.

`CreateProject` takes a free-text `prompt` plus `ProjectType` and optional
`ProjectConfig` (`style`, `genre`, `target_platform`/`audience`,
`quality_level`, `ConstraintsConfig` carrying `max_budget`, `max_tokens`,
`max_gpu_hours`, `deadline`). Enums encode the production model: `ProjectType`
(`GAME`, `MOVIE`, `SERIES`, `SHORT_FILM`, `GAME_EXPANSION`, `PROTOTYPE`);
`PhaseType` — 20 values across pre-production (`CONCEPT`, `STORY`, `DESIGN`,
`PLANNING`), production (`ASSET_CREATION`, `LEVEL_DESIGN`, `ANIMATION`, `VFX`,
`AUDIO`, `PROGRAMMING`), post-production (`INTEGRATION`, `TESTING`, `POLISH`,
`LOCALIZATION`, `RELEASE`), and movie-specific (`CINEMATOGRAPHY`, `EDITING`,
`COLOR_GRADING`, `SOUND_DESIGN`, `SCORE`); `AgentType` — 18 values across
creative (`STORY_DIRECTOR`, `CHARACTER_WRITER`, `DIALOGUE_WRITER`,
`WORLD_BUILDER`, `CONCEPT_ARTIST`, `CINEMATOGRAPHER`), technical
(`TECHNICAL_DIRECTOR`, `LEVEL_DESIGNER`, `ANIMATOR`, `VFX_ARTIST`,
`SOUND_DESIGNER`, `COMPOSER`), management (`PRODUCER`, `QA_LEAD`,
`LEGAL_CLEARANCE`), and specialized (`AI_TRAINER`, `PERFORMANCE_OPTIMIZER`,
`LOCALIZATION_MANAGER`); `QualityGateType` (`NARRATIVE_CONSISTENCY`,
`VISUAL_QUALITY`, `AUDIO_QUALITY`, `PERFORMANCE`, `GAMEPLAY`, `ACCESSIBILITY`,
`LEGAL_COMPLIANCE`, `TECHNICAL`); plus `ProjectStatus`, `PhaseStatus`,
`TaskStatus`, `TaskPriority`, `QualityGateStatus`, `UpdateType`.
`PipelineUpdate` (streamed) carries an `UpdateType`, project/phase/task IDs, a
`message`, and a string map of `data`.

---

## 8. Knowledge & Worldbuilding Service Definitions

This section covers Sophia (knowledge retrieval and graph) and Hathor
(worldbuilding and narrative). Both domains declare multiple services inside a
single `.proto` file, each owning a well-defined slice of the domain. The split
means a consumer that only needs search never has to stand up the citation or
knowledge-graph service.

### 8.1 `sophia/sophia.proto` — Knowledge Engine (package `oshun.sophia`)

`sophia.proto` declares **five services**. Each service owns one layer of the
knowledge stack: `SophiaSearchService` is the query surface,
`SophiaDocumentService` handles ingest and lifecycle, `SophiaCitationService`
manages attribution, `SophiaKnowledgeGraphService` manages the structured
entity/relation graph, and `SophiaIndexService` manages the underlying search
indexes. Streaming RPCs are noted.

**`SophiaSearchService` — 7 RPCs**

| RPC                    | Request               | Response              | Kind          |
| ---------------------- | --------------------- | --------------------- | ------------- |
| `Search`               | `SearchRequest`       | `SearchResponse`      | unary         |
| `SearchStreaming`      | `SearchRequest`       | `SearchResult`        | server-stream |
| `MultiSearch`          | `MultiSearchRequest`  | `MultiSearchResponse` | unary         |
| `HybridSearch`         | `HybridSearchRequest` | `SearchResponse`      | unary         |
| `AskQuestion`          | `AskQuestionRequest`  | `AnswerResponse`      | unary         |
| `AskQuestionStreaming` | `AskQuestionRequest`  | `AnswerChunk`         | server-stream |
| `FindSimilar`          | `FindSimilarRequest`  | `FindSimilarResponse` | unary         |

**`SophiaDocumentService` — 9 RPCs** (`IngestDocument`, `IngestBatch` →
`stream IngestionProgress`, `GetDocument`, `UpdateDocument`, `DeleteDocument` →
`common.SuccessResponse`, `ListDocuments`, `GetDocumentChunks`,
`GetIngestionStatus`, `ListIngestionJobs`).

**`SophiaCitationService` — 7 RPCs** (`CreateCitation`, `GetCitation`,
`UpdateCitation`, `DeleteCitation` → `common.SuccessResponse`, `ListCitations`,
`VerifyCitation`, `GetCitationSources`).

**`SophiaKnowledgeGraphService` — 16 RPCs:** entity ops (`CreateEntity`,
`GetEntity`, `UpdateEntity`, `DeleteEntity` → `common.SuccessResponse`,
`ListEntities`, `MergeEntities`), relation ops (`CreateRelation`, `GetRelation`,
`UpdateRelation`, `DeleteRelation` → `common.SuccessResponse`, `ListRelations`),
graph queries (`GetSubgraph`, `FindPaths`, `GetNeighbors`), and entity
resolution (`ResolveEntity`, `SuggestMerges`). All unary.

**`SophiaIndexService` — 7 RPCs** (`CreateIndex`, `GetIndex`, `UpdateIndex`,
`DeleteIndex` → `common.SuccessResponse`, `ListIndexes`, `RebuildIndex` →
`stream RebuildProgress`, `GetIndexStats`).

`SearchRequest` carries `query`, optional `index_id`, `limit`, `min_score`,
repeated `SearchFilter` (`field`/`operator`/`value` — operator one of
`eq, ne, gt, lt, gte, lte, in, contains`), and `include_content`/`highlight`
flags. `HybridSearchRequest` adds `semantic_weight`/`keyword_weight` (0.0–1.0,
default 0.5 each). `FindSimilarRequest` uses a
`oneof target { document_id; chunk_id; text }`. `IngestDocumentRequest` uses a
`oneof source { url; bytes content; text }` and accepts a
`SophiaChunkingStrategy` plus `chunk_size`/`chunk_overlap` and a
`SophiaEmbeddingProvider`. `SophiaEntity` carries `aliases`, a `properties` map,
and an optional `canonical_id` (entity-merge linkage). `EntityPath` (from
`FindPaths`) is a sequence of `entity_ids` + `relation_ids` + `total_weight`.
Enums: `SophiaDocumentStatus` (`PENDING`, `PROCESSING`, `INDEXED`, `FAILED`,
`ARCHIVED`); `SophiaDocumentType` (`PDF`, `HTML`, `MARKDOWN`, `PLAIN_TEXT`,
`DOCX`, `EPUB`, `JSON`); `SophiaEntityType` (`PERSON`, `ORGANIZATION`,
`LOCATION`, `CONCEPT`, `EVENT`, `WORK`, `CUSTOM`); `SophiaRelationType`
(`RELATED_TO`, `PART_OF`, `INSTANCE_OF`, `DERIVED_FROM`, `AUTHOR_OF`,
`LOCATED_IN`, `OCCURRED_AT`, `CUSTOM`); `SophiaChunkingStrategy` (`FIXED`,
`SEMANTIC`, `SLIDING_WINDOW`, `SENTENCE`, `PARAGRAPH`);
`SophiaEmbeddingProvider` (`OPENAI`, `COHERE`, `LOCAL`, `HUGGINGFACE`).

### 8.2 `hathor/hathor.proto` — Worldbuilding & Narrative (package `oshun.hathor`)

`hathor.proto` declares **seven services**, each owning one dimension of a
fictional world: the world container, factions, characters, locations, timeline,
narrative quests, and simulation runs. The fine-grained split means a character
editor only needs `HathorCharacterService`, while a procedural-city system can
call `HathorSimulationService` independently. Two RPCs are server-streams
(`StreamDialogue`, `StreamSimulation`).

**`HathorWorldService` — 12 RPCs:** world CRUD (`CreateWorld`, `GetWorld`,
`UpdateWorld`, `DeleteWorld` → `common.SuccessResponse`, `ListWorlds`),
versioning (`CreateWorldVersion`, `GetWorldVersion`, `ListWorldVersions`,
`RevertToVersion`), export/import (`ExportWorld`, `ImportWorld`), and
`ValidateWorld`. All unary.

**`HathorFactionService` — 9 RPCs:** faction CRUD (`CreateFaction`,
`GetFaction`, `UpdateFaction`, `DeleteFaction` → `common.SuccessResponse`,
`ListFactions`), relationships (`SetFactionRelation`, `GetFactionRelations`),
`UpdateFactionResources`, `GetFactionHistory`.

**`HathorCharacterService` — 9 RPCs:** character CRUD (`CreateCharacter`,
`GetCharacter`, `UpdateCharacter`, `DeleteCharacter` → `common.SuccessResponse`,
`ListCharacters`), relationships (`SetCharacterRelation`,
`GetCharacterRelations`), and dialogue (`GenerateDialogue` →
`GenerateDialogueResponse`, `StreamDialogue` → `stream DialogueChunk`).

**`HathorLocationService` — 9 RPCs:** location CRUD (`CreateLocation`,
`GetLocation`, `UpdateLocation`, `DeleteLocation` → `common.SuccessResponse`,
`ListLocations`), hierarchy (`GetLocationHierarchy`, `MoveLocation`),
connections (`SetLocationConnection`, `GetLocationConnections`).

**`HathorTimelineService` — 11 RPCs:** timeline CRUD (`CreateTimeline`,
`GetTimeline`, `UpdateTimeline`, `DeleteTimeline` → `common.SuccessResponse`,
`ListTimelines`), events (`AddEvent`, `UpdateEvent`, `DeleteEvent` →
`common.SuccessResponse`, `GetEvents`), event dependencies (`SetEventDependency`
→ `common.SuccessResponse`, `GetEventDependencies`).

**`HathorNarrativeService` — 12 RPCs:** quest CRUD (`CreateQuest`, `GetQuest`,
`UpdateQuest`, `DeleteQuest` → `common.SuccessResponse`, `ListQuests`),
generation (`GenerateQuest`, `GenerateQuestChain`), dialogue trees
(`CreateDialogueTree`, `GetDialogueTree`, `UpdateDialogueTree`,
`ListDialogueTrees`), and `ValidateNarrative`.

**`HathorSimulationService` — 7 RPCs:** simulation runs (`StartSimulation`,
`StopSimulation` → `common.SuccessResponse`, `GetSimulationStatus`,
`ListSimulations`), `StreamSimulation` → `stream SimulationUpdate`, scenario
generation (`GenerateScenario`, `EvaluateScenario`).

`HathorWorld` carries `WorldSettings` (`calendar_system`, `currency_name`,
optional `magic_system`/`technology_level`) and `WorldStats` (faction/character/
location/quest/event counts). `HathorFaction` carries `FactionResources`
(`wealth`, `military_power`, `political_influence`, `population` as int64, plus
a custom-resource int64 map); `FactionRelation` carries an int32 `reputation`
documented as `-100 to 100`. `HathorCharacter` carries `CharacterTraits`
(personality/motivations/flaws/skills/background) and `CharacterStats` (`level`,
`health`, attributes map); `CharacterRelation` carries an int32 `affinity`
(`-100 to 100`). `HathorQuest` carries repeated `QuestObjective` and
`QuestRewards` (experience/currency/items/reputation). `DialogueTree` is a
recursive `DialogueNode` graph (`DialogueChoice` references `next_node_id`).
Enums: `HathorWorldStatus`, `HathorFactionType` (7 values: `NATION`,
`ORGANIZATION`, `GUILD`, `TRIBE`, `CORPORATION`, `RELIGION`, `CUSTOM`),
`HathorCharacterRole`, `HathorLocationType` (8 values), `HathorQuestType`,
`HathorQuestStatus`, `HathorSimulationType` (`ECONOMY`, `POLITICS`, `CULTURE`,
`WARFARE`, `FULL`), `HathorRelationSentiment` (`HOSTILE`, `UNFRIENDLY`,
`NEUTRAL`, `FRIENDLY`, `ALLIED`).

### 8.3 `isis/isis.proto` — Generative Factory (package `oshun.isis`)

`isis.proto` is the internal gRPC surface of the Isis generative factory — the
services used by the job queue, worker pool, and tooling that inspects the
factory's output. (The product-facing generation-control plane lives in
`shared/generation_control.proto`; these four services are the lower-level
execution layer.) `isis.proto` declares **four services**. Three RPCs are
server-streams (`StreamJobProgress`, `ExportBatch`, `LoadModel`).

**`IsisJobService` — 11 RPCs:** job lifecycle (`SubmitJob`, `GetJob`,
`ListJobs`, `CancelJob` → `common.SuccessResponse`, `RetryJob`),
`StreamJobProgress` → `stream JobProgressUpdate`, batch (`SubmitBatch`,
`GetBatch`), and queue management (`GetQueueStats`, `PauseQueue` →
`common.SuccessResponse`, `ResumeQueue` → `common.SuccessResponse`).

**`IsisWorkflowService` — 12 RPCs:** workflow CRUD (`CreateWorkflow`,
`GetWorkflow`, `UpdateWorkflow`, `DeleteWorkflow` → `common.SuccessResponse`,
`ListWorkflows`), versioning (`CreateWorkflowVersion`, `GetWorkflowVersion`,
`ListWorkflowVersions`, `SetActiveVersion`), `ValidateWorkflow`, and templates
(`ListWorkflowTemplates`, `ApplyTemplate`).

**`IsisOutputService` — 7 RPCs:** output retrieval (`GetOutput`, `ListOutputs`,
`DeleteOutput` → `common.SuccessResponse`), provenance (`GetProvenance`,
`GetLineage`), and export (`ExportOutput`, `ExportBatch` →
`stream ExportProgressUpdate`).

**`IsisModelService` — 8 RPCs:** model CRUD (`RegisterModel`, `GetModel`,
`UpdateModel`, `DeleteModel` → `common.SuccessResponse`, `ListModels`), and
status (`GetModelStatus`, `LoadModel` → `stream ModelLoadProgress`,
`UnloadModel` → `common.SuccessResponse`).

`IsisJob` carries `workflow_id`/`workflow_version`, `IsisJobStatus`,
`IsisJobPriority`, a `parameters` string map, repeated `IsisOutput`,
estimated/actual duration in ms, and `worker_id`. `IsisWorkflow` carries an
`IsisWorkflowEngine`, an `active_version`, and optional input/output
`WorkflowSchema` (each a list of typed `WorkflowParameter`).
`IsisWorkflowVersion` holds the workflow `definition` as a JSON string.
`IsisOutput` carries `IsisOutputType`, `content_hash`, size/mime.
`ProvenanceInfo` records `workflow_id`/`version`, parameters, `seed`,
`model_ids`, `worker_version`. `LineageNode` is recursive (ancestors +
descendants). Enums: `IsisJobStatus` (`PENDING`, `QUEUED`, `PROCESSING`,
`COMPLETED`, `FAILED`, `CANCELLED`, `PAUSED`); `IsisJobPriority` (`LOW`,
`NORMAL`, `HIGH`, `CRITICAL`); `IsisWorkflowEngine` (`COMFYUI`, `BLENDER`,
`CUSTOM`); `IsisOutputType` (9 values incl. `GAUSSIAN_SPLAT`, `POINT_CLOUD`);
`IsisModelType` (`CHECKPOINT`, `LORA`, `VAE`, `CONTROLNET`, `UPSCALER`,
`EMBEDDING`, `CUSTOM`).

---

## 9. Concordia Service Definitions

### 9.1 `concordia/concordia.proto` — Cooperative Mediation & Negotiation (package `oshun.concordia`)

`concordia.proto` defines the gRPC contract for live mediation and negotiation
sessions. Because parties in a dispute have adversarial interests, the schema
enforces a privacy boundary at the protocol level: every RPC that surfaces
party-generated content (transcripts, offers, search results) is scoped by a
`ConcordiaViewerRole`, and the services implementing these RPCs MUST apply
`@concordia/contracts` projections before emitting messages. A caucus transcript
from Party A can never appear in Party B's stream, and private negotiation
strategy is never visible in the shared stream.

Authored for Phase 179.2.2.2. The file header states a hard invariant: every RPC
that surfaces party-generated content is scoped by a `ConcordiaViewerRole`, and
services MUST apply the `@concordia/contracts` projections before emitting any
stream message — private artifacts never traverse opposing-party or shared
streams. `concordia.proto` declares **three streaming-oriented services**.

**`ConcordiaSessionService` — 3 RPCs** (live-session transcription)

| RPC             | Request                      | Response                | Kind        |
| --------------- | ---------------------------- | ----------------------- | ----------- |
| `StreamSession` | `StreamSessionClientMessage` | `StreamSessionEvent`    | bidi-stream |
| `PauseSession`  | `PauseSessionRequest`        | `PauseSessionResponse`  | unary       |
| `ResumeSession` | `ResumeSessionRequest`       | `ResumeSessionResponse` | unary       |

`StreamSessionClientMessage` is a
`oneof kind { SessionStart session_start; AudioFrame audio_frame; SessionCommand command }`
— the first message MUST be a `SessionStart` (declaring `case_id`,
`participating_party_ids`, `AudioEncoding`, `sample_rate_hz`, BCP-47
`language_tag`, `enable_co_mediator_suggestions`, and `pinned_model_versions`).
`AudioFrame` carries raw `bytes audio` plus a monotonic `sequence` and
`captured_at`. `StreamSessionEvent` is a
`oneof kind { TranscriptUpdate; SpeakerDiarizationUpdate; CoMediatorSuggestion; SessionAck; SessionPrivacyNotice; SessionError }`.
`TranscriptUpdate` carries a revisable `transcript_id`/`revision`, `party_id`,
`text`, `confidence`, start/end times, `is_final`, and a `visibility` string (a
caucus transcript never carries `shared_with_all`). `CoMediatorSuggestion`
carries an `InterventionKind`, `suggested_wording`, `rationale`, `urgency_score`
(0..1), and a `socio_cognitive_label`. `SessionError` embeds
`oshun.common.Error` and a `terminal` flag. Enums: `AudioEncoding` (`LINEAR16`,
`OPUS`, `FLAC`); `InterventionKind` (10 values: `REFRAME`, `SUMMARIZE`,
`NAME_INTEREST`, `REDIRECT_FOCUS`, `CHECK_UNDERSTANDING`, `BRAINSTORM_OPTIONS`,
`EMOTIONAL_ACKNOWLEDGMENT`, `COOL_DOWN_BREAK`, `SAFETY_ESCALATION`,
`PROPOSE_AGREEMENT_TEST`); nested `SessionCommand.Kind` and
`SessionPrivacyNotice.Kind`.

**`ConcordiaNegotiationService` — 2 RPCs** (offer/counter exchange)

| RPC                 | Request                    | Response           | Kind        |
| ------------------- | -------------------------- | ------------------ | ----------- |
| `StreamNegotiation` | `NegotiationClientMessage` | `NegotiationEvent` | bidi-stream |
| `SubmitOffer`       | `SubmitOfferRequest`       | `NegotiationEvent` | unary       |

`NegotiationClientMessage` is a
`oneof kind { NegotiationStart; OfferMessage; CounterMessage; WithdrawMessage; AcceptMessage; NegotiationPing }`.
`OfferMessage` references an existing `candidate_id` **or** carries inline
`InlineOfferTerm`s (each with a JSON-bytes `structured_json` payload parsed
through the `@concordia/contracts` AgreementDSL). `NegotiationEvent` is a
`oneof kind { OfferAccepted; OfferRejected; OfferExpired; CounterProposed; AgreementReached; NegotiationPong; NegotiationNotice }`.
`OfferAccepted` carries a `nash_product`; `AgreementReached` carries a
`per_party_utility` map (visible only where shared-view projection allows).
`NegotiationNotice.Kind` covers `COOLING_OFF_ACTIVE`, `AUTHORITY_GAP`,
`REVIEWER_REQUIRED`, `BOUNDARY_BLOCKED`, `CONSENT_REVOKED`, `REDLINE_HIT`.

**`ConcordiaSearchService` — 2 RPCs** (agreement-search progress)

| RPC                    | Request                       | Response               | Kind          |
| ---------------------- | ----------------------------- | ---------------------- | ------------- |
| `StreamSearchProgress` | `StreamSearchProgressRequest` | `SearchProgressEvent`  | server-stream |
| `CancelSearch`         | `CancelSearchRequest`         | `CancelSearchResponse` | unary         |

`StreamSearchProgressRequest` carries `case_id`, `search_run_id`, a
`resume_from_seq` for reconnect, and a `viewer_role` for projection.
`SearchProgressEvent` has an `event_seq`, `emitted_at`, and a
`oneof kind { SearchStarted; SearchIteration; CandidateGenerated; FrontierSnapshot; SearchCompleted; SearchFailed; SearchCancelled; SearchKernelMetric }`.
`SearchStarted` records the `kernel` string (matching the OpenAPI `SearchKernel`
enum), `max_iterations`, and `max_wall_clock_seconds`. `SearchIteration` reports
`best_nash_product`, `mean_utility_uncertainty`, and
`redline_violations_pruned`. `FrontierSnapshot` carries viewer-projected
Pareto-optimal `candidate_ids`, `total_candidates_evaluated`, and a
`diversity_score`. `SearchFailed` embeds `oshun.common.Error`.

`proto.spec.ts` explicitly loads `concordia.proto` and asserts the three
services exist and that `getServiceMetadata` reports the streaming RPC names
(`StreamSession`/`PauseSession`/`ResumeSession`, `StreamNegotiation`/
`SubmitOffer`, `StreamSearchProgress`/`CancelSearch`). These metadata `methods`
arrays for the three Concordia services are accurate against source.

---

## 10. Shared Substrate Service Definitions

The `shared/` directory is architecturally distinct from the domain service
files in §6–§9. Domain services (`isis/`, `sophia/`, `auth/`, etc.) are
engineering-internal: they implement the platform's infrastructure and are
consumed by other backend services. The shared substrate services are
product-facing: they are the gRPC surfaces that the OSHUN product domains (Tara,
Arete, Veritas, Nyx, Nisaba, and the Assistant shell) call directly. The
boundary exists so that product domains always talk to a stable, versioned
substrate contract — `shared/evidence.proto`, `shared/memory.proto`, etc. — and
never depend directly on engineering-internal service internals that might
change without notice.

The four `shared/*.proto` files (plus `shared/common.proto`) define
**product-facing substrate contracts** — gRPC surfaces consumed by the OSHUN
product domains (Tara, Arete, Veritas, Nyx, Nisaba, the Assistant shell). They
are distinct from the engineering-internal domain services above.

### 10.1 `shared/common.proto` — package `oshun.shared.common`

No service. Provides cross-substrate enums and version descriptors:
`SharedContractCompatibilityMode` (`BACKWARD_COMPATIBLE`, `FORWARD_TOLERANT`,
`STRICT`, `MIXED_ROLLOUT`); `SharedConsumer` (`ASSISTANT`, `TARA`, `ARETE`,
`VERITAS`, `NYX`, `NISABA`, `ADMIN`, `STUDIO`, `SUPPORT`); `SharedDomain`
(`SHARED`, `TARA`, `ARETE`, `VERITAS`, `NYX`, `NISABA`); `SharedServiceStatus`
(`OK`, `DEGRADED`, `UNAVAILABLE`). Message `SharedContractVersionDescriptor`
carries `contract_id`, `version`, `minimum_compatible_version`, supported and
deprecated version lists, a `SharedContractCompatibilityMode`, and notes.

### 10.2 `shared/evidence.proto` — `OshunEvidenceService` (package `oshun.shared.evidence`)

9 RPCs, all unary — Sophia's product-facing evidence/grounding surface. Imports
`google/protobuf/struct.proto` and `shared/common.proto`.

| RPC                     | Request                            | Response                                              |
| ----------------------- | ---------------------------------- | ----------------------------------------------------- |
| `GetContractDescriptor` | `oshun.common.Empty`               | `oshun.shared.common.SharedContractVersionDescriptor` |
| `GetMetadata`           | `oshun.common.Empty`               | `EvidenceMetadata`                                    |
| `GetAvailability`       | `oshun.common.Empty`               | `EvidenceAvailability`                                |
| `Search`                | `EvidenceSearchRequest`            | `EvidenceSearchResponse`                              |
| `Ground`                | `EvidenceGroundingRequest`         | `GroundedAnswer`                                      |
| `AssembleEvidencePack`  | `EvidencePackAssemblyRequest`      | `EvidencePack`                                        |
| `VerifyClaims`          | `EvidenceClaimVerificationRequest` | `EvidenceClaimVerificationResponse`                   |
| `SaveToNotebook`        | `EvidenceSaveNotebookRequest`      | `EvidenceNotebookRecord`                              |
| `ExportEvidenceTrace`   | `EvidenceTraceExportRequest`       | `EvidenceTraceExportRecord`                           |

`GroundedAnswer` is the central type: `answer` text, `EvidenceGroundingStatus`,
`confidence`, citation trail, `EvidenceSourceSummary`s, `EvidenceClaimCheck`s,
notebooks, an `EvidenceSourceGraphPreview`, and an embedded `EvidencePack`.
`EvidenceItem` carries an `EvidenceStance` (`SUPPORTS`, `CONTRADICTS`,
`CONTEXT`, `QUOTE`, `NEUTRAL`). Enums: `EvidenceSubjectKind` (9 values),
`EvidenceCitationPolicy` (`REQUIRED`, `PREFERRED`, `OPTIONAL`),
`EvidenceGroundingStatus` (`GROUNDED`, `PARTIALLY_GROUNDED`, `UNSUPPORTED`,
`CONFLICTING`), `EvidenceSearchKind` (6 values), `EvidenceStance`,
`EvidenceTraceExportKind` (`BIBLIOGRAPHY`, `EVIDENCE_TABLE`, `GROUNDED_REPORT`,
`REVIEW_PACKET`), `EvidenceTraceExportFormat` (`JSON`, `CSV`, `MARKDOWN`,
`PDF`).

### 10.3 `shared/memory.proto` — `OshunMemoryService` (package `oshun.shared.memory`)

11 RPCs, all unary — the Iris memory/continuity substrate.

| RPC                       | Request                  | Response                       |
| ------------------------- | ------------------------ | ------------------------------ |
| `GetMetadata`             | `oshun.common.Empty`     | `MemoryMetadata`               |
| `GetAvailability`         | `oshun.common.Empty`     | `MemoryAvailability`           |
| `ResolveAssistantProfile` | `MemoryUserRequest`      | `AssistantProfileResponse`     |
| `GetContinuityState`      | `ContinuityStateRequest` | `ContinuityState`              |
| `GetConsentSummary`       | `MemoryUserRequest`      | `MemoryConsentSummaryResponse` |
| `ReviewMemory`            | `MemoryReviewRequest`    | `MemoryReviewResult`           |
| `Search`                  | `MemorySearchRequest`    | `MemorySearchResponse`         |
| `PlanWrite`               | `MemoryWriteInput`       | `MemoryWritePlan`              |
| `Remember`                | `MemoryWriteInput`       | `MemoryRecordsResponse`        |
| `Forget`                  | `MemoryForgetRequest`    | `MemoryDeleteSummary`          |
| `ExportMemory`            | `MemoryExportRequest`    | `MemoryExportRecord`           |

`MemoryRecord` carries `MemoryTier`, `MemoryScope`, importance, access counters,
`MemoryPrivacyStatus`, a `SharedDomain`, related-memory IDs, a
`google.protobuf.Struct` `metadata`, and search-ranking fields. `PlanWrite`
returns a `MemoryWritePlan` evaluating `MemoryMode`, `MemoryStorageTarget`,
required/missing `MemoryConsentType`s, and opt-out blockers before any write.
`Remember` performs the write; `Forget` (with `MemoryDeleteMode` SOFT/HARD)
deletes. Enums (14 total) include `MemoryTier` (`CORE`, `WORKING`, `ARCHIVAL`,
`EPISODIC`, `SEMANTIC`), `MemoryScope` (7 values), `MemoryMode` (`DURABLE`,
`EPHEMERAL`, `SUPPRESSED`), `MemorySearchStrategy` (`SEMANTIC`, `KEYWORD`,
`TEMPORAL`, `HYBRID`, `ADAPTIVE`), `MemoryConsentType` (13 named values),
`MemoryLegalBasis` (6 GDPR-aligned bases), `MemoryStateIndicator`,
`MemoryConsentRollup`, `MemoryStorageTarget`, `MemorySearchMatchType`,
`MemoryConsentStatus`, `MemoryExportFormat`.

### 10.4 `shared/persona_policy.proto` — `OshunPersonaPolicyService` (package `oshun.shared.persona`)

10 RPCs, all unary — the Lilith persona-policy substrate.

| RPC                   | Request                   | Response                        |
| --------------------- | ------------------------- | ------------------------------- |
| `GetMetadata`         | `oshun.common.Empty`      | `PersonaPolicyMetadata`         |
| `GetAvailability`     | `oshun.common.Empty`      | `PersonaPolicyAvailability`     |
| `ListPolicyPacks`     | `oshun.common.Empty`      | `PersonaPolicyPackListResponse` |
| `ResolvePolicyPack`   | `PersonaIdRequest`        | `PersonaPolicyPackResponse`     |
| `SelectPolicy`        | `PolicySelectionInput`    | `PolicySelection`               |
| `GetToneGuidance`     | `PersonaIdRequest`        | `ToneGuidanceResponse`          |
| `AssessSafety`        | `SafetyAssessmentRequest` | `SafetyAssessment`              |
| `CheckTopicScope`     | `TopicScopeRequest`       | `TopicScopeResult`              |
| `BuildPromptOverlay`  | `PolicyEvaluationInput`   | `PromptOverlay`                 |
| `EvaluateInteraction` | `PolicyEvaluationInput`   | `PolicyEvaluationResult`        |

`PersonaPolicyPack` is the central type: persona/family/category/tradition,
`ToneGuidance` (warmth/formality/pace/directness/complexity, rhetorical
devices), core principles, allowed/forbidden topics, disclaimers, a
`PolicyGroundingRequirement`, a `PolicyMemoryEnvelope`, a `VoiceSafetyPolicy`,
and a `PolicyPackStatus`. `EvaluateInteraction` returns a
`PolicyEvaluationResult` bundling selection, `SafetyAssessment`,
`TopicScopeResult`, tone guidance, a `PromptOverlay`, and a
`PolicySafetyDisposition`. Enums: `PolicyGroundingRequirement` (`NOT_NEEDED`,
`RECOMMENDED`, `REQUIRED`), `PolicyMemoryEnvelope` (`NONE`, `SESSION`, `SCOPED`,
`DURABLE`), `PolicySafetyDisposition` (`ALLOW`, `ALLOW_WITH_DISCLAIMER`,
`REDIRECT`, `ESCALATE`, `BLOCK`), `PolicyRiskLevel` (`NONE`..`CRITICAL`),
`PolicyContentCategory`, `PolicyPackStatus`, `VoiceSafetyClass` (`STANDARD`,
`WATERMARKED`, `CLONE_RESTRICTED`, `PUBLIC_CLONE_PROHIBITED`), `VoiceUsageType`
(`PERSONAL`, `PUBLIC`, `COMMERCIAL`, `EDUCATIONAL`).

### 10.5 `shared/generation_control.proto` — `OshunGenerationControlService` (package `oshun.shared.generation`)

14 RPCs, all unary — the Isis generation-control plane.

| RPC                            | Request                       | Response                             |
| ------------------------------ | ----------------------------- | ------------------------------------ |
| `GetContractDescriptor`        | `oshun.common.Empty`          | `SharedContractVersionDescriptor`    |
| `GetMetadata`                  | `oshun.common.Empty`          | `GenerationControlMetadata`          |
| `GetAvailability`              | `oshun.common.Empty`          | `GenerationControlAvailability`      |
| `ListWorkflowCatalog`          | `oshun.common.Empty`          | `WorkflowCatalogListResponse`        |
| `GetWorkflowCatalogEntry`      | `WorkflowIdRequest`           | `WorkflowCatalogEntryResponse`       |
| `ListModelCatalog`             | `oshun.common.Empty`          | `ModelCatalogListResponse`           |
| `GetModelCatalogEntry`         | `ModelIdRequest`              | `ModelCatalogEntryResponse`          |
| `GetProviderRoutingSummary`    | `oshun.common.Empty`          | `ProviderRoutingSummary`             |
| `PlanGeneration`               | `ControlledGenerationRequest` | `GenerationControlPlan`              |
| `DispatchGeneration`           | `ControlledGenerationRequest` | `GenerationExecutionSummary`         |
| `GetGenerationExecution`       | `GenerationJobIdRequest`      | `GenerationExecutionSummaryResponse` |
| `GetProvenanceBundle`          | `OutputIdRequest`             | `ProvenanceBundleResponse`           |
| `GetReleaseReadiness`          | `ReleaseReadinessRequest`     | `ReleaseReadiness`                   |
| `ListRetentionPolicySummaries` | `oshun.common.Empty`          | `RetentionPolicySummaryListResponse` |

`PlanGeneration` evaluates routing/policy/readiness and returns a
`GenerationControlPlan` (provider family + endpoint, policy bundles, retention
policy, a `ReleaseReadiness` rollup, provenance/watermark/quality-gate flags,
estimated cost/duration, blocked reasons). `DispatchGeneration` actually
launches and returns a `GenerationExecutionSummary` (status, progress,
`BudgetGuardrailMode`, `QualityGateMode`, output counts). Enums (19 total)
include `ControlPlaneEnvironment`, `GenerationJobStatus`,
`GenerationJobPriority`, `GenerationType` (15 named values: `TEXT_TO_IMAGE` …
`TEXTURE_UPSCALE`), `WorkflowEngine`, `WorkflowVisibility`, `WorkflowStatus`,
`WorkflowCategory` (12 named values), `WorkflowPipelineStage`, `ModelType`,
`ModelFormat` (8 named values), `ModelCompatibleEngine`, `ProviderFamily` (11
named values), `OutputFileType`, `OutputStatus`, `StorageTier` (`HOT`, `WARM`,
`COLD`, `GLACIER`), `ReleaseGateMode`, `BudgetGuardrailMode`, `QualityGateMode`.

---

## 11. Rendering & 3D Service Definitions

This section covers the four services that form the 3D content creation and
rendering pipeline. `Generation3DService` creates geometry from AI models
(text-to-3D, image-to-3D). `GaussianSplattingService` reconstructs real-world
scenes from photo or video capture using Gaussian Splatting and NeRF.
`ProceduralGenService` generates large environments algorithmically via Houdini.
`RenderingService` submits and tracks render jobs across a farm of render nodes.
Together these four cover the full pipeline from raw input to finished render.

### 11.1 `generation3d/generation3d.proto` — `Generation3DService` (package `oshun.generation3d`)

23 RPCs spanning text-to-3D, image-to-3D, mesh processing, auto-rigging, texture
generation, and job management. Three are server-streams
(`StreamTextToModelProgress`, `StreamImageToModelProgress`,
`StreamAutoRigProgress` — all taking `StreamProgressRequest`); the rest unary.
RPC roster: `TextToModel`, `StreamTextToModelProgress`, `BatchTextToModel`,
`ImageToModel`, `MultiViewToModel`, `StreamImageToModelProgress`,
`OptimizeMesh`, `GenerateLODs`, `AnalyzeMesh`, `UnwrapUVs`, `CleanupMesh`,
`AutoRig`, `StreamAutoRigProgress`, `GenerateWeights`, `SetupIKFK`,
`GenerateTextures`, `BakeTextures`, `GenerateAtlas`, `GetJob`, `ListJobs`,
`CancelJob` → `common.SuccessResponse`, `RetryJob`, `GetJobResult`. Generation
RPCs return `GenerationJobResponse` (`job_id` + `Job3DStatus` + `Job3DType` +
estimated seconds + queue position); mesh RPCs return `MeshProcessingResponse`;
`GenerateLODs` returns `LODGenerationResponse`; `AnalyzeMesh` returns
`MeshAnalysisResponse`; rigging RPCs return `RiggingJobResponse`; texture RPCs
return `TextureJobResponse`. `StreamAutoRigProgress` emits `RiggingProgress`
(`current_bone`, `bones_processed`/`total_bones`). `Model3DMetadata` carries
format, poly/vertex/ material counts, texture maps, a `BoundingBox`, and
`has_uvs`/`has_normals`/ `has_animations`/`is_rigged` flags. Enums:
`Generation3DProvider` (`RODIN`, `MESHY`, `TRIPO`, `TRELLIS`, `HUNYUAN`,
`THREEDFY`, `LOCAL`); `OutputFormat3D` (`GLB`, `GLTF`, `FBX`, `OBJ`, `USD`,
`USDZ`, `STL`, `PLY`); `QualityPreset` (`DRAFT`, `STANDARD`, `HIGH`, `ULTRA`);
`Job3DStatus`; `Job3DType` (8 values); `SkeletonType` (`HUMANOID`, `QUADRUPED`,
`BIRD`, `CUSTOM`); `Category3D` (11 values).

### 11.2 `rendering/rendering.proto` — `RenderingService` (package `oshun.rendering`)

27 RPCs covering render jobs, previews, render farms, render nodes, outputs,
presets, and statistics. One server-stream (`StreamJobProgress`); the rest
unary. RPC roster: job ops (`SubmitJob`, `GetJob`, `CancelJob`, `RetryJob`,
`ListJobs`, `StreamJobProgress` → `stream JobProgress`); previews
(`RequestPreview`, `GetPreviewStatus`); farms (`ListFarms`, `GetFarm`,
`CreateFarm`, `UpdateFarm`, `DeleteFarm` → `common.SuccessResponse`); nodes
(`ListNodes`, `GetNode`, `RegisterNode`, `DeregisterNode` →
`common.SuccessResponse`, `UpdateNodeStatus`); outputs (`GetOutput`,
`ListOutputs`, `DownloadOutput`); presets (`ListPresets`, `GetPreset`,
`CreatePreset`, `UpdatePreset`, `DeletePreset` → `common.SuccessResponse`); and
`GetRenderStats`. `RenderJob` carries a `RenderEngine`, `RenderSettings`
(`Resolution`, samples, motion blur, denoising, repeated `RenderPass`,
`OutputFormat`, `use_gpu`), a `FrameRange`, and frame counters. `JobProgress`
(streamed) carries frames-completed/total, percent, current frame/node, and a
latest `FrameResult`. `RenderNode` carries `NodeCapabilities` (engines, GPU
models, OS), `NodeResources`, and `NodeResourceUsage`. Enums: `RenderEngine`
(`BLENDER_CYCLES`, `BLENDER_EEVEE`, `GODOT`, `UNREAL`, `ARNOLD`, `VRAY`,
`OCTANE`, `REDSHIFT`); `RenderJobStatus` (8 values incl. `COMPOSITING`);
`RenderPriority`; `OutputFormat` (8 values incl. `MP4`, `MOV`, `WEBM`, `GIF`);
`NodeStatus`; `FarmType` (`LOCAL`, `CLOUD`, `HYBRID`).

### 11.3 `splatting/gaussian_splatting.proto` — `GaussianSplattingService` (package `oshun.splatting`)

37 RPCs — the 3D Gaussian Splatting + NeRF pipeline. One client-stream
(`UploadFrames`) and two server-streams (`StreamTrainingProgress`,
`StreamRenderProgress`); the rest unary. RPC sections:

- **Capture (10):** `StartCapture`, `ConfigureCamera` →
  `common.SuccessResponse`, `UploadFrames` (`stream UploadFrameRequest` →
  `UploadFramesResponse`, **client-stream**), `ProcessVideo`, `ExtractFrames`,
  `AssessFrameQuality`, `GenerateMasks`, `EndCapture`, `GetCaptureSession`,
  `ListCaptureSessions`.
- **Training (9):** `TrainSplat`, `StreamTrainingProgress` →
  `stream TrainingProgress`, `GetTrainingMetrics`, `PauseTraining` →
  `common.SuccessResponse`, `ResumeTraining`, `CancelTraining` →
  `common.SuccessResponse`, `SaveCheckpoint`, `LoadCheckpoint`,
  `ListCheckpoints`.
- **NeRF (3):** `TrainNeRF`, `ConvertNeRFToSplat`, `ExportNeRFToMesh`.
- **Rendering (6):** `RenderView`, `RenderViews`, `RenderVideo`,
  `StreamRenderProgress` → `stream RenderProgress`, `StartRenderSession`,
  `EndRenderSession` → `common.SuccessResponse`.
- **Export (5):** `ExportSplat`, `ExportForEngine`, `ExportCompressed`,
  `ExportLODs`, `ExportPointCloud`.
- **Model management (4):** `GetSplatModel`, `ListSplatModels`,
  `DeleteSplatModel` → `common.SuccessResponse`, `OptimizeSplatModel`.

`UploadFrameRequest` carries raw `bytes image_data` plus optional `camera_id`,
`CameraExtrinsics` (flattened 3×3 rotation + translation + intrinsics +
distortion), `depth_data`, and `mask_data`. `TrainingConfig` exposes the full
3DGS training surface (`iterations`, per-attribute learning rates, `sh_degree`,
`densification_interval`, `densify_grad_threshold`, `max_gaussians`).
`TrainingProgress` (streamed) reports `current_iteration`, `loss`,
`psnr`/`ssim`/`lpips`, and `num_gaussians`. `SplatModelStats` records `psnr`,
`ssim`, `lpips`, training iterations/seconds. Enums: `SplatProvider` (`3DGS`,
`MIP_SPLATTING`, `SCAFFOLD_GS`, `GSGEN`, `DREAMGAUSSIAN`, `SUGAR`, `LOCAL`);
`NeRFProvider` (`INSTANT_NGP`, `NERFSTUDIO`, `MIPNERF360`, `NERFACTO`,
`TENSORF`, `PLENOXELS`, `LOCAL`); `SplatJobStatus` (11 values incl.
`PREPROCESSING`, `TRAINING`, `RENDERING`, `EXPORTING`); `CaptureType`
(`SINGLE_CAMERA`, `MULTI_CAMERA`, `VIDEO`, `TURNTABLE`, `DRONE`, `HANDHELD`);
`ExportFormat` (`PLY`, `SPLAT`, `KSPLAT`, `NPZ`, `UNITY`, `UNREAL`, `WEB`,
`POINT_CLOUD`); `TargetEngine` (`UNITY`, `UNREAL`, `GODOT`, `WEB`, `NATIVE`).

### 11.4 `procedural/procedural.proto` — `ProceduralGenService` (package `oshun.procedural`)

41 RPCs — Houdini-based procedural generation of terrain, cities, biomes,
dungeons, space environments, and asset scatter. Four server-streams
(`StreamTerrainProgress`, `StreamCityProgress`, `StreamBiomeProgress`,
`StreamDungeonProgress` — all `StreamProgressRequest` →
`stream GenerationProgress`); the rest unary.

> **The service is declared `service ProceduralGenService`.** The
> `SERVICE_NAMES.Procedural` registry entry
> (`oshun.procedural.ProceduralGenerationService`) does not match the source —
> see §13.

RPC sections: terrain (`GenerateTerrain`, `StreamTerrainProgress`,
`ApplyErosion`, `GenerateWaterFeatures`, `GenerateVegetationMask`,
`StitchTerrains`, `ExportTerrain`, `PreviewTerrain`); city (`GenerateCity`,
`StreamCityProgress`, `GenerateRoadNetwork`, `GenerateBuildingBlocks`,
`GenerateBuildings`, `GenerateInfrastructure`, `ExportCity`); biome
(`GenerateBiome`, `StreamBiomeProgress`, `GenerateVegetation`, `GenerateRocks`,
`GenerateWildlifePaths`, `ExportBiome`); dungeon (`GenerateDungeon`,
`StreamDungeonProgress`, `GenerateConnections`, `PopulateDungeon`,
`ExportDungeon`); space (`GenerateStarSystem`, `GeneratePlanet`,
`GenerateAsteroidField`, `GenerateNebula`, `ExportSpaceEnvironment`); scatter
(`ScatterAssets`, `GenerateInstanceData`, `ExportScatterData`); job management
(`GetJob`, `ListJobs`, `CancelJob` → `common.SuccessResponse`, `GetJobResult`);
template management (`ListTemplates`, `GetTemplate`, `CreateTemplate`).
Generation RPCs return `ProceduralJobResponse`; export RPCs return
`ExportJobResponse`. `TerrainConfig` carries repeated `NoiseLayer` (each a
`NoiseType` + amplitude/frequency/octaves/lacunarity/persistence), an
`ErosionConfig`, and a `WaterConfig`. Enums: `ProceduralJobStatus`;
`ProceduralJobType` (`TERRAIN`, `CITY`, `BIOME`, `DUNGEON`, `SPACE`, `SCATTER`);
`NoiseType` (`PERLIN`, `SIMPLEX`, `VALUE`, `RIDGE`, `WORLEY`, `FBM`,
`TURBULENCE`, `BILLOWY`); `ErosionType` (`HYDRAULIC`, `THERMAL`, `WIND`,
`COASTAL`, `GLACIAL`); `TerrainExportFormat` (7 values); `BiomeType` (12
values); `CityStyle` (10 values); `DungeonStyle` (8 values).

---

## 12. Engine Bridge & Infrastructure Service Definitions

This section covers the bridge services (Blender, Godot, Unreal) and the
infrastructure services (health, load balancing, reflection, and the V2 game
economy). The bridge services all follow the same pattern: an addon or plugin
installed inside the DCC application opens a gRPC server, and the platform
connects to it using these service definitions to drive the application
programmatically. The infrastructure services (health, load balancing,
reflection) are standard gRPC ecosystem patterns rather than domain-specific
schemas.

### 12.1 `bridge/blender.proto` — `BlenderBridgeService` (package `oshun.bridge.blender`)

32 RPCs — a control surface over a running Blender instance via a Blender addon.
Three server-streams (`RenderSequence` → `stream RenderProgress`,
`StreamExecuteScript` → `stream ScriptOutput`, `StreamEvents` →
`stream BlenderEvent`); the rest unary. RPC sections: connection (`Connect`,
`Disconnect` → `common.SuccessResponse`, `GetStatus`, `Heartbeat`); scene
(`GetScene`, `CreateScene`, `SaveScene` → `common.SuccessResponse`,
`LoadScene`); object (`ListObjects`, `GetObject`, `CreateObject`,
`UpdateObject`, `DeleteObject` → `common.SuccessResponse`, `DuplicateObject`);
material (`ListMaterials`, `GetMaterial`, `CreateMaterial`, `UpdateMaterial`,
`AssignMaterial` → `common.SuccessResponse`); animation (`GetAnimation`,
`SetKeyframe` → `common.SuccessResponse`, `PlayAnimation` →
`common.SuccessResponse`, `StopAnimation` → `common.SuccessResponse`); rendering
(`RenderFrame`, `RenderSequence`, `GetRenderSettings`, `UpdateRenderSettings`);
Python execution (`ExecuteScript`, `StreamExecuteScript`); asset I/O
(`ImportAsset`, `ExportAsset`); and `StreamEvents`. `BlenderObject` carries an
`ObjectType` and a `Transform` (`Vector3` location/rotation/scale).
`SetKeyframe` carries a `google.protobuf.Struct` `value`. Enum: `ObjectType`
(`MESH`, `CURVE`, `SURFACE`, `ARMATURE`, `EMPTY`, `CAMERA`, `LIGHT`, `SPEAKER`,
`VOLUME`).

### 12.2 `bridge/godot.proto` — `GodotBridgeService` (package `oshun.bridge.godot`)

28 RPCs — a control surface over a running Godot editor. Three server-streams
(`StreamSignals` → `stream SignalEvent`, `ExportProject` →
`stream ExportProgress`, `StreamEvents` → `stream GodotEvent`); the rest unary.
RPC sections: connection (`Connect`, `Disconnect` → `common.SuccessResponse`,
`GetStatus`); project (`GetProject`, `OpenScene`, `SaveScene` →
`common.SuccessResponse`, `ReloadScene`); scene tree (`GetSceneTree`, `GetNode`,
`CreateNode`, `UpdateNode`, `DeleteNode` → `common.SuccessResponse`,
`ReparentNode`, `DuplicateNode`); resources (`GetResource`, `CreateResource`,
`SaveResource` → `common.SuccessResponse`, `ListResources`); scripts
(`GetScript`, `UpdateScript`, `ExecuteMethod`); signals (`EmitSignal` →
`common.SuccessResponse`, `ConnectSignal` → `common.SuccessResponse`,
`StreamSignals`); editor ops (`RunProject`, `StopProject` →
`common.SuccessResponse`, `ExportProject`); and `StreamEvents`. `GodotNode`
carries `Transform2D` and `Transform3D` and a
`map<string, google.protobuf.Value>` of properties; `ExecuteMethod` and
`EmitSignal` pass `repeated google.protobuf.Value` arguments. No enums.

### 12.3 `bridge/unreal.proto` — `UnrealBridgeService` (package `oshun.bridge.unreal`)

56 RPCs — the largest service in the library, a control surface over a running
Unreal Engine editor. Four server-streams (`BuildProject` →
`stream BuildProgress`, `RenderSequence` → `stream RenderProgress`,
`StreamEvents` → `stream UnrealEvent`, `StreamLogs` → `stream LogEntry`); the
rest unary. RPC sections: connection (`Connect`, `Disconnect`, `GetStatus`,
`Heartbeat`); project (`GetProject`, `OpenProject`, `SaveProject` →
`common.SuccessResponse`, `BuildProject`); level (`ListLevels`, `GetLevel`,
`OpenLevel`, `SaveLevel` → `common.SuccessResponse`, `CreateLevel`); actor
(`ListActors`, `GetActor`, `SpawnActor`, `UpdateActor`, `DestroyActor` →
`common.SuccessResponse`, `DuplicateActor`); component (`ListComponents`,
`GetComponent`, `AddComponent`, `UpdateComponent`, `RemoveComponent` →
`common.SuccessResponse`); blueprint (`ListBlueprints`, `GetBlueprint`,
`CreateBlueprint`, `CompileBlueprint`, `GetBlueprintGraph`); material
(`ListMaterials`, `GetMaterial`, `CreateMaterial`, `UpdateMaterial`,
`AssignMaterial` → `common.SuccessResponse`); animation (`ListAnimations`,
`GetAnimation`, `PlayAnimation` → `common.SuccessResponse`, `StopAnimation` →
`common.SuccessResponse`, `GetSequencer`, `ControlSequencer`); asset
(`ListAssets`, `GetAsset`, `ImportAsset`, `ExportAsset`, `ReimportAsset`);
rendering (`CaptureViewport`, `RenderSequence`, `GetRenderSettings`,
`UpdateRenderSettings`); Play-In-Editor (`StartPIE`, `StopPIE` →
`common.SuccessResponse`, `GetPIEStatus`); console (`ExecuteConsoleCommand`,
`ExecutePython`); and `StreamEvents` / `StreamLogs`. `UnrealActor` carries a
`Transform` (`Vector3` location/scale + `Rotator` pitch/yaw/roll). Enums:
`EngineMode` (`EDITOR`, `PIE`, `STANDALONE`, `SERVER`); `BlueprintType`;
`MaterialDomain` (6 values); `BlendMode` (`OPAQUE`, `MASKED`, `TRANSLUCENT`,
`ADDITIVE`, `MODULATE`); `ShadingModel` (11 values); `AnimationType`;
`SequencerCommand`; `ImageFormat` (`PNG`, `JPEG`, `EXR`, `BMP`); `PIEMode` (6
values); `LogVerbosity` (8 values).

### 12.4 `health/health.proto` — `HealthService` (package `oshun.health`)

The gRPC standard health-checking pattern. Two RPCs:

| RPC     | Request              | Response              | Kind          |
| ------- | -------------------- | --------------------- | ------------- |
| `Check` | `HealthCheckRequest` | `HealthCheckResponse` | unary         |
| `Watch` | `HealthCheckRequest` | `HealthCheckResponse` | server-stream |

`HealthCheckRequest` carries a `service` string (empty = overall server health).
`HealthCheckResponse` carries a `ServingStatus` enum (`SERVING_STATUS_UNKNOWN`,
`SERVING_STATUS_SERVING`, `SERVING_STATUS_NOT_SERVING`,
`SERVING_STATUS_SERVICE_UNKNOWN`). The file comments note `SERVICE_UNKNOWN` is
only used for `Watch`; `Check` returns a `NOT_FOUND` gRPC status instead. This
is a distinct definition from `common/types.proto`'s
`HealthCheckRequest`/`HealthCheckResponse` pair (which carries a richer
`HealthStatus` and `ServiceCheck` list, §6.1) — the two are not the same
message.

### 12.5 `loadbalancing/loadbalancing.proto` — `LoadBalancingService` (package `oshun.loadbalancing`)

5 RPCs. One server-stream (`WatchEndpoints`); the rest unary.

| RPC              | Request                 | Response               | Kind          |
| ---------------- | ----------------------- | ---------------------- | ------------- |
| `GetEndpoints`   | `GetEndpointsRequest`   | `GetEndpointsResponse` | unary         |
| `WatchEndpoints` | `WatchEndpointsRequest` | `EndpointUpdate`       | server-stream |
| `ReportHealth`   | `ReportHealthRequest`   | `ReportHealthResponse` | unary         |
| `GetPolicy`      | `GetPolicyRequest`      | `LoadBalancingPolicy`  | unary         |
| `UpdatePolicy`   | `UpdatePolicyRequest`   | `LoadBalancingPolicy`  | unary         |

Imports `google/protobuf/duration.proto`. `Endpoint` carries host/port,
`EndpointHealth`, `weight`, `priority`, a `Locality` (region/zone/sub-zone), and
a metadata map. `LoadBalancingPolicy` aggregates a `LoadBalancingStrategy`, a
`HealthCheckConfig`, a `RetryPolicy` (max retries, exponential backoff via
`backoff_multiplier`, retryable status codes), a `CircuitBreakerConfig`, an
`OutlierDetectionConfig`, a `RingHashConfig`, and a `LocalityConfig`.
`ReportHealthRequest` carries `LatencyStats` (p50/p90/p99/avg). Enums:
`LoadBalancingStrategy` (`ROUND_ROBIN`, `WEIGHTED_ROUND_ROBIN`, `PICK_FIRST`,
`LEAST_CONNECTIONS`, `RANDOM`, `RING_HASH`, `LOCALITY_AWARE`); `EndpointHealth`
(`HEALTHY`, `UNHEALTHY`, `DEGRADED`, `DRAINING`); `UpdateType` (`ADDED`,
`MODIFIED`, `REMOVED`).

### 12.6 `reflection/reflection.proto` — `ServerReflectionService` (package `oshun.reflection`)

The gRPC standard server-reflection pattern. One RPC:

| RPC                    | Request                   | Response                   | Kind        |
| ---------------------- | ------------------------- | -------------------------- | ----------- |
| `ServerReflectionInfo` | `ServerReflectionRequest` | `ServerReflectionResponse` | bidi-stream |

> **The service is declared `service ServerReflectionService`.** The
> `SERVICE_NAMES.Reflection` registry entry
> (`oshun.reflection.ReflectionService`) does not match — see §13.

`ServerReflectionRequest` carries a `host` and a `oneof message_request`
(`file_by_filename`, `file_containing_symbol`, `file_containing_extension` →
`ExtensionRequest`, `all_extension_numbers_of_type`, `list_services`).
`ServerReflectionResponse` carries a `oneof message_response`
(`FileDescriptorResponse` with serialized `FileDescriptorProto` bytes,
`ExtensionNumberResponse`, `ListServiceResponse`, `ErrorResponse`). This is the
schema for the standard reflection protocol that lets tools like `grpcurl`
discover services on a running server.

### 12.7 `oshun/v2/persistent_economy/economy.proto` — package `oshun.v2.persistent_economy`

A single file declaring **three small services** for Section-130 open-world game
systems. All RPCs unary.

**`Economy` — 3 RPCs:** `GetShopInventory` (`GetShopInventoryRequest` →
`ShopInventory`), `GetPriceCurve` (`GetPriceCurveRequest` → `PriceCurve`),
`RecordTransaction` (`RecordTransactionRequest` → `TransactionAck`).

**`NPCSchedule` — 1 RPC:** `GetActiveSchedule` (`GetActiveScheduleRequest` →
`ActiveSchedule`).

**`CrimeRate` — 1 RPC:** `GetDistrictRate` (`GetDistrictRateRequest` →
`DistrictCrimeRate`).

`ShopInventory` carries a `daily_seed` and `weekly_vehicle_part_seed` (shared
across all players for fairness) plus repeated `ShopInventoryItem`
(`price_minor` as int64, `demand_priced`, `premium_shop_migration`).
`PriceCurve` carries `demand_percentile`/`supply_percentile`, a
`price_multiplier`, and an `event_topic`. `RecordTransactionRequest` carries an
`account_id` and an `ip_rate_bucket` for anti-bot rate caps; `TransactionAck`
returns `accepted`, `anti_bot_flagged`, and an `event_topic`. `ActiveSchedule`
carries repeated `NPCScheduleRow` (routine block, district, interaction,
`behavior_intent`). `DistrictCrimeRate` carries `crime_rate_percent` (0–100),
`cop_spawn_density`, and a `lockdown_active` flag. This file has no enums — all
discriminators are strings. `proto.spec.ts` loads it and asserts the three
services (`Economy`, `NPCSchedule`, `CrimeRate`) exist.

---

## 13. Registry / Source Discrepancy Ledger

The TypeScript registries in `services.ts` are hand-maintained. Over time they
have drifted from the `.proto` sources in three classes of ways. This section is
a complete ledger of known discrepancies so consumers always know which artifact
is authoritative. The short answer: for any service name or RPC method list,
trust the `.proto` file, not the registry value.

The TypeScript registries in `services.ts` are hand-maintained and have drifted
from the `.proto` sources in three classes of way. These are documented here so
consumers know which artifact is authoritative.

**A. Service-name mismatches (the registry value is not the wire name).**

| Registry entry             | `SERVICE_NAMES` value                          | Actual `.proto` service                                | Wire-correct name                          |
| -------------------------- | ---------------------------------------------- | ------------------------------------------------------ | ------------------------------------------ |
| `SERVICE_NAMES.Procedural` | `oshun.procedural.ProceduralGenerationService` | `service ProceduralGenService` (`procedural.proto`)    | `oshun.procedural.ProceduralGenService`    |
| `SERVICE_NAMES.Reflection` | `oshun.reflection.ReflectionService`           | `service ServerReflectionService` (`reflection.proto`) | `oshun.reflection.ServerReflectionService` |

A gRPC client constructed by reading the package object from `loadProto` will
find the service at the `.proto`-declared name, not the `SERVICE_NAMES` value.

**B. `getServiceMetadata` `methods` arrays are partial / stale.** The `methods`
array on each `ServiceMetadata` is a hand-written subset that has not tracked
`.proto` changes. Examples confirmed against source: `AI` metadata names a
`GenerateAudio`/`Generate3DModel`/`GenerateEmbeddings` shortlist that does not
match the 26 actual `AIService` RPCs; `Agent` metadata names
`CreateAgent`/`DeleteAgent`/`RunAgent`, none of which exist (the real RPCs are
`RegisterAgent`/`DeregisterAgent`/`AssignTask`/etc.); `Asset`, `Project`,
`User`, `Generation3D`, `Rendering`, `GaussianSplatting`, `Procedural`,
`Pipeline`, `LoadBalancing` metadata arrays are likewise partial. The Concordia
and shared- substrate metadata arrays _are_ accurate. **§6–§12 of this document,
derived directly from the `.proto` files, are authoritative for RPC rosters.**

**C. The metadata table has no entry for every service.** `getServiceMetadata`
covers the services keyed in `SERVICE_NAMES`, but where a single `.proto` file
declares several services (Isis: 4, Sophia: 5, Hathor: 7, Concordia: 3) each is
a separate `SERVICE_NAMES` key with its own metadata record.

These are factual observations about the current code, not defects this document
is empowered to fix (the assignment scope is the two `DOMAINS/proto` docs only).
They are recorded so the spec does not silently launder the drift.

---

## 14. Buf Toolchain Configuration

`@oshun/proto` uses [buf](https://buf.build) to manage the proto lifecycle. Buf
replaces raw `protoc` invocations with a declarative, reproducible pipeline: a
workspace file declares where the module root is, a module config declares lint
rules and external dependencies, and a generation config declares exactly which
plugins run and where they write output. This means any engineer can run
`buf lint` and `buf generate` and get the same result without installing
separate plugin binaries.

`@oshun/proto` uses [buf](https://buf.build) for proto linting, breaking-change
detection, and code generation. Three buf files exist.

### 14.1 `buf.work.yaml` (library root)

```yaml
version: v1
directories:
  - src
```

Declares the buf workspace. The single workspace directory is `src`, so the
module root is `libs/proto/src/` and all imports resolve relative to it (which
is why `import "common/types.proto"` works).

### 14.2 `src/buf.yaml` (single module config)

```yaml
version: v1
name: buf.build/oshun/proto
lint:
  use:
    - DEFAULT
    - COMMENTS
  except:
    - PACKAGE_VERSION_SUFFIX
    - SERVICE_SUFFIX
    - RPC_REQUEST_RESPONSE_UNIQUE
    - RPC_REQUEST_STANDARD_NAME
    - RPC_RESPONSE_STANDARD_NAME
  enum_zero_value_suffix: _UNSPECIFIED
  rpc_allow_same_request_response: false
  rpc_allow_google_protobuf_empty_requests: true
  rpc_allow_google_protobuf_empty_responses: true
  allow_comment_ignores: true
breaking:
  use:
    - FILE
  except:
    - FIELD_SAME_JSON_NAME
    - ENUM_VALUE_NO_DELETE
deps:
  - buf.build/googleapis/googleapis
```

There is exactly **one** `buf.yaml`, at `src/buf.yaml`. It declares the buf
module `buf.build/oshun/proto` and covers the entire `src/` tree — there are no
per-domain `buf.yaml` files.

- **Lint.** Uses the `DEFAULT` rule group plus `COMMENTS` (every public API
  element must be documented — this is why every service/RPC/message in the
  library carries a doc comment). Five rules are disabled:
  `PACKAGE_VERSION_SUFFIX` (so packages can be `oshun.ai`, not `oshun.ai.v1`),
  `SERVICE_SUFFIX` (the `Service` suffix is used by convention but not
  enforced), and three RPC request/response naming rules
  (`RPC_REQUEST_RESPONSE_UNIQUE`, `RPC_REQUEST_STANDARD_NAME`,
  `RPC_RESPONSE_STANDARD_NAME`) — which is why many RPCs legitimately share
  request types (e.g. `GetGenerationResultRequest` is reused by three AI RPCs;
  `GetUserRequest` by five User RPCs). `enum_zero_value_suffix` is set to
  `_UNSPECIFIED`. `rpc_allow_same_request_response: false` still forbids an RPC
  using the _same_ type for request and response.
  `rpc_allow_google_protobuf_ empty_requests`/`_responses: true` permits —
  though the library actually uses its own `oshun.common.Empty`, not
  `google.protobuf.Empty`. `allow_comment_ignores: true` lets a
  `// buf:lint:ignore` comment suppress a rule locally.
- **Breaking.** Uses the `FILE` rule group (file-level breaking-change
  detection) with two exceptions: `FIELD_SAME_JSON_NAME` and
  `ENUM_VALUE_NO_DELETE`.
- **Deps.** Declares one external module dependency:
  `buf.build/googleapis/googleapis` (for the well-known `google.protobuf.*`
  imports).

### 14.3 `buf.gen.yaml` (library root) — Code Generation

```yaml
version: v1
managed:
  enabled: true
  go_package_prefix:
    default: github.com/oshun/proto/gen/go
plugins:
  - plugin: buf.build/community/stephenh-ts-proto
    out: gen/ts
    opt:
      [
        esModuleInterop=true,
        outputServices=grpc-js,
        env=node,
        useOptionals=messages,
        exportCommonSymbols=false,
        snakeToCamel=true,
        stringEnums=true,
        forceLong=long,
        outputTypeRegistry=true,
        useDate=true,
      ]
  - plugin: buf.build/protocolbuffers/go
    out: gen/go
    opt: [paths=source_relative]
  - plugin: buf.build/grpc/go
    out: gen/go
    opt: [paths=source_relative]
  - plugin: buf.build/community/chrusty-protoc-gen-jsonschema
    out: gen/jsonschema
    opt:
      [
        all_fields_required,
        disallow_additional_properties,
        disallow_bigints_as_strings,
        enforce_oneof,
        file_extension=.schema.json,
      ]
```

`buf generate` runs four remote plugins. Managed mode is enabled with a
`go_package_prefix` of `github.com/oshun/proto/gen/go`.

| Plugin                                              | Output           | Produces                                           |
| --------------------------------------------------- | ---------------- | -------------------------------------------------- |
| `buf.build/community/stephenh-ts-proto`             | `gen/ts`         | TypeScript message types + `grpc-js` service stubs |
| `buf.build/protocolbuffers/go`                      | `gen/go`         | Go message types                                   |
| `buf.build/grpc/go`                                 | `gen/go`         | Go gRPC service stubs                              |
| `buf.build/community/chrusty-protoc-gen-jsonschema` | `gen/jsonschema` | JSON Schema (`.schema.json`) for validation        |

The **ts-proto** plugin is the TypeScript generator (it replaces the older
`grpc-web` setup that earlier revisions of this document described). Its options
configure: `outputServices=grpc-js` (server/client stubs target `@grpc/grpc-js`,
matching the runtime dependency), `env=node`, `useOptionals=messages` (proto3
`optional` fields become TS optional properties), `snakeToCamel=true` (the
generated TS _does_ camelCase field names — note this differs from the runtime
loader's `keepCase: true`), `stringEnums=true` (enums as string-literal unions),
`forceLong=long` (64-bit ints as `long` objects), `outputTypeRegistry=true`, and
`useDate=true` (`google.protobuf.Timestamp` ↔ JS `Date`). Output directories
(`gen/ts`, `gen/go`, `gen/jsonschema`) are relative to `libs/proto/`.

### 14.4 The `generated/` Directory

`libs/proto/generated/` contains a single committed artifact: `buf-image.json`
(~2 MB) — a serialized buf _image_ (a `FileDescriptorSet` in JSON form). It
contains all **28** `.proto` files of the module as `FileDescriptorProto`
entries, **26** of which contain at least one service. A buf image is the
self-contained input buf consumes for breaking-change comparison and code
generation; it is the compiled, dependency-resolved form of the schema. The
`gen/ts`, `gen/go`, and `gen/jsonschema` output directories named in
`buf.gen.yaml` are not committed under `generated/` — they are produced on
demand by `buf generate`.

### 14.5 `scripts/generate.ts`

`scripts/generate.ts` is an alternative, **protobufjs-based** type generator,
separate from the buf toolchain. It is a `tsx`-executable ESM script that:

1. Recursively finds every `.proto` under `src/` (`findProtoFiles`).
2. Ensures `generated/` exists.
3. Locates the `pbjs` and `pbts` binaries under `node_modules/.bin/`; if either
   is absent it logs a skip notice and returns (no failure).
4. Runs `pbjs -t static-module -w es6` to emit `generated/proto.js`.
5. Runs `pbts` to emit `generated/proto.d.ts` from that JS.

This produces a single static-module pair (`proto.js` + `proto.d.ts`) covering
all schemas. It coexists with — and is independent of — the `buf generate`
pipeline; the two are different generation paths and emit to different targets.

### 14.6 Nx Targets

`project.json` defines five Nx targets:

| Target       | Executor          | Action                                                         |
| ------------ | ----------------- | -------------------------------------------------------------- |
| `build`      | `@nx/js:tsc`      | Compile TS → `dist/libs/proto`; copy `**/*.proto` to `protos/` |
| `lint`       | `@nx/eslint:lint` | ESLint over the library                                        |
| `test`       | `@nx/vite:test`   | Vitest (`passWithNoTests: true`)                               |
| `proto:gen`  | `nx:run-commands` | `pnpm exec buf generate` (cwd `libs/proto`)                    |
| `proto:lint` | `nx:run-commands` | `pnpm exec buf lint` (cwd `libs/proto`)                        |

`proto:gen` and `proto:lint` invoke buf directly. There is no Nx target wired to
`buf breaking` — breaking-change checks are run manually or in CI against the
`FILE` rule group declared in `src/buf.yaml`.

---

## 15. Tests (`src/proto.spec.ts`)

The Vitest test suite validates that the TypeScript helper layer is correctly
wired to the `.proto` files. Because this library has no domain logic — only
schema and helpers — the tests focus entirely on confirming that registries map
to the right values, the loader can parse real schema files, and the channel
constants have the expected numeric values. The suite also serves as a
regression gate: if someone renames a service in a `.proto` file without
updating a registry, the test that calls `loadProto` and reads the service
constructor will fail.

The Vitest suite `proto.spec.ts` exercises the loader and registries. It does
**not** test domain logic (there is none in this library — it is schema +
helpers). Coverage:

- **`PROTO_PATHS`** — asserts ~22 key→path pairs (`common`, `ai`, `asset`,
  `auth`, `project`, `user`, `collaboration`, the five `shared*` keys,
  `generation3d`, `rendering`, `splatting`, `persistentEconomy`, `blender`,
  `godot`, `unreal`, `health`, `loadbalancing`, `pipeline`, and `concordia`).
- **`SERVICE_NAMES`** — asserts core, shared-substrate, 3D/rendering, V2,
  bridge, and infrastructure service names match their expected literals.
- **`DEFAULT_CHANNEL_OPTIONS`** — asserts the two keepalive durations (`30000`,
  `10000`) and both 50 MB message-size limits.
- **`DEFAULT_LOADER_OPTIONS`** — asserts `keepCase: true`, `longs: String`,
  `enums: String`, `defaults: true`, `oneofs: true`.
- **`getServiceMetadata`** — asserts metadata is returned for `AI`, `Asset`,
  `Auth`, the three bridges, the four shared-substrate services, the three V2
  services, and the three Concordia services, and spot-checks selected method
  names.
- **`loadProto`** — actually parses `shared/evidence.proto`,
  `shared/memory.proto`, `shared/persona_policy.proto`,
  `shared/generation_control.proto`, `concordia/concordia.proto`, and
  `oshun/v2/persistent_economy/economy.proto`, asserting the expected package
  objects and service constructors are present. The Concordia and V2 cases drill
  into `pkg.oshun.concordia.ConcordiaSessionService` etc. and
  `pkg.oshun.v2.persistent_economy.Economy` etc.
- **Concordia metadata** — a dedicated block asserts `PROTO_PATHS.concordia`,
  the three `SERVICE_NAMES.Concordia*` values, and the streaming method names on
  each Concordia service's metadata.

`vitest.config.ts` runs in the `node` environment with `globals: true` and v8
coverage (`text`, `json`, `html` reporters).

---

## 16. Public API (`src/index.ts`)

`index.ts` is the single entry point for `@oshun/proto`. It re-exports
everything a consuming service needs in one import: the loader functions and
path registry from `loader.ts`, the service name registry and channel helpers
from `services.ts`, and a set of `@grpc/grpc-js` types re-exported for consumer
convenience — so that a domain service that only uses `@oshun/proto` as a
dependency does not also need to depend directly on `@grpc/grpc-js` for
type-only use.

`index.ts` is the package entry point. It re-exports:

**From `./loader`:** `loadProto`, `loadProtos`, `loadAllProtos`, `getProtoPath`,
`DEFAULT_LOADER_OPTIONS`, `PROTO_PATHS`, and the type `ProtoPath`.

**From `./services`:** `SERVICE_NAMES`, `DEFAULT_CHANNEL_OPTIONS`,
`createCredentials`, `getServiceMetadata`, and the types `ServiceName` and
`ServiceMetadata`.

**Re-exported `@grpc/grpc-js` types** (for consumer convenience, so a domain
service need not depend on `@grpc/grpc-js` directly for type-only use):
`Client`, `Server`, `ServiceDefinition`, `MethodDefinition`, `GrpcObject`,
`ChannelCredentials`, `ChannelOptions`, `Metadata`, `ServiceError`,
`ServerUnaryCall`, `ServerWritableStream`, `ServerReadableStream`,
`ServerDuplexStream`, `ClientUnaryCall`, `ClientWritableStream`,
`ClientReadableStream`, `ClientDuplexStream`.

The `.proto` files themselves are **not** re-exported from `index.ts`; raw
schema access is via the `package.json` `"./protos/*"` export subpath (§1.1).

---

## 17. Service Consumer Pattern

This section shows the complete, four-step pattern for establishing a gRPC
client connection using `@oshun/proto`. Every step is deliberate: using
`PROTO_PATHS` avoids hard-coded file paths, `await loadProto` is required
because schema parsing is async, reading the service constructor from the
package object (not from `SERVICE_NAMES`) ensures the wire-correct name is used,
and passing `DEFAULT_CHANNEL_OPTIONS` gives the connection the correct keepalive
and message-size settings.

A domain service that calls a gRPC service does the following (the pattern is
exercised by `proto.spec.ts`'s `loadProto` assertions):

```typescript
import {
  loadProto,
  PROTO_PATHS,
  createCredentials,
  DEFAULT_CHANNEL_OPTIONS,
} from '@oshun/proto';

// 1. Load the schema (async — loadProto returns a Promise).
const pkg = await loadProto(PROTO_PATHS.isis);

// 2. Read the service constructor from the package object, at the
//    .proto-declared fully-qualified path (package + service name).
const IsisJobService = (pkg as any).oshun.isis.IsisJobService;

// 3. Construct a client with centralized credentials + channel options.
const client = new IsisJobService(
  'isis-service:50051',
  createCredentials(process.env.NODE_ENV === 'production'),
  DEFAULT_CHANNEL_OPTIONS
);

// 4. Call an RPC. Field names follow keepCase:true — snake_case as declared.
client.getQueueStats({ queue_name: 'default' }, (err, response) => {
  if (err) throw err;
  console.log(response.pending_jobs);
});
```

Key points implied by the source:

- `loadProto` is **async** — callers must `await` it (or `.then`).
- The service is read from the package object at its `.proto`-declared path. For
  `procedural` and `reflection` this is the `.proto` service name
  (`ProceduralGenService`, `ServerReflectionService`), **not** the
  `SERVICE_NAMES` value (§13).
- Because `DEFAULT_LOADER_OPTIONS` sets `keepCase: true`, request/response field
  names at runtime are `snake_case` exactly as declared in the `.proto`. (Code
  generated by `buf generate` via ts-proto uses `snakeToCamel=true` and is
  therefore camelCased — the runtime-loader path and the codegen path differ on
  this point.)
- `createCredentials(false)` for local/insecure, `createCredentials(true, ...)`
  for TLS (§5.3).

---

## 18. Integration Points

`@oshun/proto` sits at the bottom of the dependency graph: it imports no other
Oshun library, and every domain that uses gRPC depends on it. The table below
maps each schema area to its owning or primary consuming domain, so an engineer
can find the right `.proto` file for a given domain without grepping the full
tree.

`@oshun/proto` is a leaf dependency — it imports no other Oshun library, and any
domain that speaks gRPC depends on it for the loader, registries, and channel
helpers. Observed schema-to-domain ownership:

| Schema area                                                         | Owning / consuming domain                                     |
| ------------------------------------------------------------------- | ------------------------------------------------------------- |
| `health/`, `loadbalancing/`, `reflection/`                          | Service-mesh infrastructure / health probing                  |
| `auth/`, `user/`, `project/`, `asset/`, `collaboration/`            | Core platform services                                        |
| `ai/`, `agent/`, `pipeline/`                                        | AI inference, multi-agent orchestration, autonomous pipelines |
| `isis/`, `generation3d/`, `procedural/`, `splatting/`, `rendering/` | Isis generative factory + 3D/render pipeline                  |
| `sophia/`                                                           | Sophia knowledge engine                                       |
| `hathor/`                                                           | Hathor worldbuilding & narrative                              |
| `concordia/`                                                        | Concordia cooperative-mediation domain (Phase 179)            |
| `bridge/blender.proto`, `bridge/godot.proto`, `bridge/unreal.proto` | DCC / game-engine bridge integrations                         |
| `shared/evidence.proto`                                             | Sophia product-facing evidence/grounding substrate            |
| `shared/memory.proto`                                               | Iris memory/continuity substrate                              |
| `shared/persona_policy.proto`                                       | Lilith persona-policy substrate                               |
| `shared/generation_control.proto`                                   | Isis generation-control plane                                 |
| `oshun/v2/persistent_economy/economy.proto`                         | V2 open-world game systems (Section 130)                      |

REST-over-HTTP contracts for external-facing APIs are owned separately (the
`@oshun/openapi` domain). `@oshun/proto` owns only the gRPC schema mechanics and
the runtime loading helpers.
