OschemaBuildConfig: add contexts_default(...) setter so single-bin codegen can override the ServerCli root-only default #36

Open
opened 2026-04-30 11:47:48 +00:00 by rawdaGastan · 0 comments
Member

Problem

Downstream services that consume the OSIS code generator (OschemaBuilder::new(config).single_bin(...).generate()) get an auto-generated entrypoint at bin/<name>.rs that calls ServerCli::parse(). ServerCli::contexts defaults to "root" (crates/server/src/server/cli.rs:31). When the binary is launched without --contexts and without HERO_CONTEXTS env (which is the production path via hero_proc), only root gets registered. Any client request with X-Hero-Context set to a name not in that list (e.g. default, geomind) silently falls back to root at the dispatcher layer (unified_server.rs:597-608) — every space ends up reading the same store.

Downstream services have no clean way to override that default today. Editing the generated bin/<name>.rs is futile (it's marked DO NOT EDIT and gets clobbered on schema or build.rs changes); there is no setter on OschemaBuildConfig for it; environment variables only paper over the problem at deployment time.

Concrete blocker: hero_osis #40 (lhumina_code/hero_osis#40). The hero_os UI shell defaults its active_context to "default". Out of the box, every hero_osis install has the cross-context data leak symptom because the generator picks root and default is never registered.

Proposed API

Add a contexts_default(impl Into<String>) builder method on OschemaBuildConfig (likely in crates/server/src/server/config.rs or wherever OschemaBuildConfig lives — a quick grep should locate it). When set, the generator emits a bin/<name>.rs that uses the supplied value as the contexts default in place of the upstream ServerCli "root" default. Behaviour priority preserved:

1. CLI flag --contexts <list>         (highest)
2. env var HERO_CONTEXTS=<list>
3. OschemaBuildConfig::contexts_default(...)  ← new tier
4. ServerCli upstream default "root"   (fallback)

When contexts_default(...) is NOT called, behaviour is unchanged (back-compat).

Consumer-side usage in hero_osis would look like:

OschemaBuilder::new(
    OschemaBuildConfig::new()
        .schemas_dir("../../schemas")
        .domain("communication", "...")
        // ... other config
        .single_bin("hero_osis", "Hero OSIS", "...git", "...")
        .contexts_default("root,default,geomind,incubaid,my_context,our_context,threefold,your_context,hero_osis")
)
.generate()?;

The emitted bin/hero_osis.rs would then ship with that contexts list as its default, register all of them at startup, and the cross-context isolation already present in OServer::register + unified_server::dispatch_rpc would Just Work for those names.

Implementation sketch

  1. Add contexts_default: Option<String> field to OschemaBuildConfig with builder setter.
  2. Pass that field through OschemaBuilder to whichever generator function emits the single_bin main file (likely crates/generator/src/... — search for single_bin consumer).
  3. In the generator, when emitting the let contexts: Vec<String> = cli.contexts.split(',')... block in the bin, conditionally substitute the default.
  4. Add a unit test in the generator that confirms contexts_default("a,b") produces a bin with "a,b" as the resolved default and that an explicit --contexts c still overrides it.
  5. No SDK changes; no runtime changes; purely a build-time API.

Out of scope (worth filing separately)

The deeper bug — unified_server::dispatch_rpc silently falls back to "root" for any unregistered context name — should be fixed independently (return -32602 Invalid params strict, OR auto-register on first request permissive, OR at minimum tracing::warn! on fallback). This issue (#NN above) is just the build-time API to plug the most common gap; the deeper dispatcher behaviour is its own ticket.

Found via

QA session 2026-04-29; documented in detail at hero_osis #40 (lhumina_code/hero_osis#40). The hero_osis fix attempt for #40 surfaced this missing API as the actual blocker.

## Problem Downstream services that consume the OSIS code generator (`OschemaBuilder::new(config).single_bin(...).generate()`) get an auto-generated entrypoint at `bin/<name>.rs` that calls `ServerCli::parse()`. `ServerCli::contexts` defaults to `"root"` (`crates/server/src/server/cli.rs:31`). When the binary is launched without `--contexts` and without `HERO_CONTEXTS` env (which is the production path via `hero_proc`), only `root` gets registered. Any client request with `X-Hero-Context` set to a name not in that list (e.g. `default`, `geomind`) silently falls back to `root` at the dispatcher layer (`unified_server.rs:597-608`) — every space ends up reading the same store. Downstream services have **no clean way to override that default** today. Editing the generated `bin/<name>.rs` is futile (it's marked `DO NOT EDIT` and gets clobbered on schema or build.rs changes); there is no setter on `OschemaBuildConfig` for it; environment variables only paper over the problem at deployment time. Concrete blocker: hero_osis #40 (https://forge.ourworld.tf/lhumina_code/hero_osis/issues/40). The hero_os UI shell defaults its `active_context` to `"default"`. Out of the box, every hero_osis install has the cross-context data leak symptom because the generator picks `root` and `default` is never registered. ## Proposed API Add a `contexts_default(impl Into<String>)` builder method on `OschemaBuildConfig` (likely in `crates/server/src/server/config.rs` or wherever `OschemaBuildConfig` lives — a quick grep should locate it). When set, the generator emits a `bin/<name>.rs` that uses the supplied value as the contexts default *in place of* the upstream `ServerCli` `"root"` default. Behaviour priority preserved: ``` 1. CLI flag --contexts <list> (highest) 2. env var HERO_CONTEXTS=<list> 3. OschemaBuildConfig::contexts_default(...) ← new tier 4. ServerCli upstream default "root" (fallback) ``` When `contexts_default(...)` is NOT called, behaviour is unchanged (back-compat). Consumer-side usage in hero_osis would look like: ```rust OschemaBuilder::new( OschemaBuildConfig::new() .schemas_dir("../../schemas") .domain("communication", "...") // ... other config .single_bin("hero_osis", "Hero OSIS", "...git", "...") .contexts_default("root,default,geomind,incubaid,my_context,our_context,threefold,your_context,hero_osis") ) .generate()?; ``` The emitted `bin/hero_osis.rs` would then ship with that contexts list as its default, register all of them at startup, and the cross-context isolation already present in `OServer::register` + `unified_server::dispatch_rpc` would Just Work for those names. ## Implementation sketch 1. Add `contexts_default: Option<String>` field to `OschemaBuildConfig` with builder setter. 2. Pass that field through `OschemaBuilder` to whichever generator function emits the `single_bin` main file (likely `crates/generator/src/...` — search for `single_bin` consumer). 3. In the generator, when emitting the `let contexts: Vec<String> = cli.contexts.split(',')...` block in the bin, conditionally substitute the default. 4. Add a unit test in the generator that confirms `contexts_default("a,b")` produces a bin with `"a,b"` as the resolved default and that an explicit `--contexts c` still overrides it. 5. No SDK changes; no runtime changes; purely a build-time API. ## Out of scope (worth filing separately) The deeper bug — `unified_server::dispatch_rpc` silently falls back to `"root"` for any unregistered context name — should be fixed independently (return `-32602 Invalid params` strict, OR auto-register on first request permissive, OR at minimum `tracing::warn!` on fallback). This issue (#NN above) is just the build-time API to plug the most common gap; the deeper dispatcher behaviour is its own ticket. ## Found via QA session 2026-04-29; documented in detail at hero_osis #40 (https://forge.ourworld.tf/lhumina_code/hero_osis/issues/40). The hero_osis fix attempt for #40 surfaced this missing API as the actual blocker.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_rpc#36
No description provided.