Migrate OSIS services off OServer onto hero_rpc2 (#90 Phase 1) #97

Merged
timur merged 3 commits from issue-90-phase1-framework into development 2026-05-20 23:00:40 +00:00
Owner

Phase 1 of #90. Hard-cut OServer + legacy emitters; flip scaffolder default to hero_rpc2.

Shipped:

  1. hero_rpc2 transport — POST /rpc (was /), three GET well-known endpoints (/health, /openrpc.json, /.well-known/heroservice.json), ServiceInfo via ServerBuilder::with_service_info, rpc.health builtin auto-registered.
  2. hero_rpc_osis::rpc::rpc2_adapter — bridges Arc<A: OsisAppRpcHandler> → jsonrpsee::RpcModule with CRUD-by-typename + service-method routing + HeroRequestContext → RequestContext projection (the hybrid-decision seam).
  3. Hard cut: deleted crates/server/ entirely (3,362 LoC), legacy SDK + bin emitters, recipe_sdk_rpc2 example, all bin_*/single_bin config. Flipped generate_rpc2_sdk default to true. Scaffolder template rewritten. recipe_server migrated end-to-end — single demo on new path.

Validation: cargo check --workspace + cargo test --workspace --lib --bins clean; hero_rpc2 uds-http suite (27 tests incl. new http_well_known.rs) green; example/recipe_server builds clean. Two pre-existing test failures on development (sse_proxy, two stale osis examples) flagged but untouched — orthogonal to #90.

Not in this PR (phases 2+): migrating hero_service / hero_logic / hero_compute / hero_db to hero_rpc2 dispatch — those are separate sweeps.

Phase 1 of #90. Hard-cut OServer + legacy emitters; flip scaffolder default to hero_rpc2. **Shipped:** 1. **hero_rpc2 transport** — POST /rpc (was /), three GET well-known endpoints (/health, /openrpc.json, /.well-known/heroservice.json), ServiceInfo via ServerBuilder::with_service_info, rpc.health builtin auto-registered. 2. **hero_rpc_osis::rpc::rpc2_adapter** — bridges Arc<A: OsisAppRpcHandler> → jsonrpsee::RpcModule with CRUD-by-typename + service-method routing + HeroRequestContext → RequestContext projection (the hybrid-decision seam). 3. **Hard cut**: deleted crates/server/ entirely (3,362 LoC), legacy SDK + bin emitters, recipe_sdk_rpc2 example, all bin_*/single_bin config. Flipped generate_rpc2_sdk default to true. Scaffolder template rewritten. recipe_server migrated end-to-end — single demo on new path. **Validation**: cargo check --workspace + cargo test --workspace --lib --bins clean; hero_rpc2 uds-http suite (27 tests incl. new http_well_known.rs) green; example/recipe_server builds clean. Two pre-existing test failures on development (sse_proxy, two stale osis examples) flagged but untouched — orthogonal to #90. **Not in this PR (phases 2+):** migrating hero_service / hero_logic / hero_compute / hero_db to hero_rpc2 dispatch — those are separate sweeps.
feat(hero_rpc2): route POST /rpc + serve well-known endpoints (#90)
Some checks failed
Test / test (push) Failing after 2m46s
0648239c93
Skill `hero_sockets` mandates four endpoints on every `rpc.sock`:
POST /rpc, GET /health, GET /openrpc.json, GET /.well-known/heroservice.json.
hero_rpc2's HTTP transport previously only handled POST /. Now:

- POST /rpc dispatches JSON-RPC (was POST /). Other paths return 404.
- GET /health and GET /.well-known/heroservice.json synthesised from the
  new ServiceInfo plumbed through ServerBuilder::with_service_info.
- GET /openrpc.json serves the same value cached by with_discover(...),
  404 if no discover spec was configured (router treats it as "service
  can't describe itself").
- New rpc.health JSON-RPC builtin (closes #80 root cause) auto-registered
  by serve_http; opt-out by calling register_rpc_health first.

Client transport's post_once also POSTs to /rpc now.

Tests:
- Updated http_hero_rpc_compat + http_context_lift to POST /rpc.
- Added http_well_known.rs (health / discovery / openrpc.json / rpc.health
  pinning) so hero_router discovery shape doesn't regress silently.
Closes the framework-side seam for issue #90 Phase 1: services that
generate `Arc<A: OsisAppRpcHandler>` via OSchema codegen can now plug
straight into `hero_rpc2::ServerBuilder` without re-implementing the
dispatch loop OServer owned.

`hero_rpc_osis::rpc::rpc2_adapter::module_for(app)` returns a
`jsonrpsee::RpcModule<()>` that:
- registers `<type>.{get,set,delete,find,exists,list}` for every type in
  `A::type_names()`, routed to `handle_rpc_call_with_context` with the
  same param-shape extraction OServer's domain_dispatch did (sid for
  get/delete/exists, query for find, data-or-object for set);
- registers every method in `A::openrpc_spec()` not colliding with the
  CRUD set or with hero_rpc2's own builtins (`rpc.discover`/`rpc.health`),
  routed to `handle_service_call_with_context`;
- maps hero_rpc2's `HeroRequestContext` (lifted from `X-Hero-Context` /
  `X-Hero-Claims` / `X-Forwarded-Prefix`) into the OSIS `RequestContext`
  shape per call;
- translates OSIS `RpcError` kinds back into JSON-RPC error codes per #83
  (same mapping OServer used).

Hero_rpc2 + jsonrpsee gated behind the existing `rpc` feature on
hero_rpc_osis; no impact on the data-only path.
chore(#90 Phase 1): hard-cut OServer + legacy emitters; flip scaffolder to hero_rpc2
Some checks failed
Test / test (push) Failing after 1m33s
Test / test (pull_request) Failing after 1m48s
f828383ce1
This is the bulk of hero_rpc#90 Phase 1 after the framework primitives
landed in the earlier two commits. Per the design comment thread on the
issue, the migration is a hard cut (no deprecation window) — every
piece of OServer-era plumbing without an external caller is deleted,
the surviving callable pieces are re-homed in hero_rpc_osis, and the
scaffolder + recipe_server reference all assume hero_rpc2 from this
commit forward.

## What's deleted

* `crates/server/` — the entire OServer crate (3,362 LoC). ACL module
  (824 LoC, zero external callers), `ContextRegistry`/`git_sync`/
  `context.*`/`domain.*` management RPC methods, `seed_from_dir`,
  `inspector_ui`, all of it. Workspace member dropped.
* `crates/generator/src/build/emit/rust_sdk.rs` — legacy SDK emitter
  that targeted the deleted OServer wire shape.
* `crates/generator/src/build/emit/bin.rs` — per-domain / single-bin
  orchestrator emitter (OServer-baked). Composite services like
  hero_osis now ship their own bin code.
* `OschemaBuildConfig`: `generate_rust_sdk` field + `with_rust_sdk()`
  builder + every `bin_*` / `single_bin` / `SingleBinConfig` config
  (used only by the deleted bin emitter).
* `example/recipe_sdk_rpc2/` — folded into recipe_server, which is now
  the single end-to-end demo on the new path.
* `layout::title_case_acronym_aware` — only caller was the deleted
  bin emitter.

## What flips defaults

* `OschemaBuildConfig::generate_rpc2_sdk` defaults to `true`. New
  `without_hero_rpc2_sdk()` opt-out for the rare build script that
  produces its Rust client through a different path.
* Scaffolder's emitted `main.rs` template now drives hero_rpc2 +
  rpc2_adapter directly: builds a `jsonrpsee::RpcModule`, hands it to
  `ServerBuilder::serve_http`, and reads the socket path from the
  binary's embedded `service.toml`. The OServer-style `run_cli`
  callback is gone.
* Scaffolder's emitted `service.toml` socket path is now `{svc}/`,
  matching the `hero_sockets` skill (no `_server` / `_admin` suffix
  in the directory name).
* Scaffolder's emitted `Cargo.toml` for `*_server` now depends on
  `hero_rpc2` + `jsonrpsee` instead of `hero_rpc_server`.

## What's migrated

* `example/recipe_server` ships the new shape end-to-end:
  - `crates/hero_recipes_server/src/main.rs` rewritten to use
    `hero_rpc2::ServerBuilder` + `rpc2_adapter`.
  - `crates/hero_recipes_server/service.toml` socket path moved to
    `hero_recipes/rpc.sock` (the canonical `hero_sockets` shape).
  - `crates/hero_recipes/build.rs` opts into the rpc2 SDK.
  - `Cargo.toml` patch section drops `hero_rpc_server`, adds
    `hero_rpc2`.
  - `sdk/rust/Cargo.toml` now depends on `hero_rpc2 + jsonrpsee`
    instead of the deleted `hero_rpc_client`.
  - Stale `sdk/rust/src/recipes/` (legacy emitter output) removed —
    `sdk/rust/src/recipes.rs` (the rpc2 trait file) is canonical.

## Test fixes

* `crates/generator/src/build/scaffold.rs` test asserts updated to
  pin the new template's call sites (`hero_rpc2::prelude::*`,
  `ServerBuilder::new(module)`, `.serve_http(&rpc_socket)`,
  `rpc2_adapter::register_methods(...)`).
* `crates/generator/src/build/emit/rust_rpc2.rs::flag_defaults_off`
  renamed to `flag_defaults_on_after_phase1_cutover` (the default
  flipped).
* `crates/oschema/tests/real_schemas.rs`: drop the three
  `crates/server/examples/recipe_server/…` cases — those paths went
  with `crates/server/`. The `example/recipe_server/schemas/` case
  remains and covers the canonical shape.

## Verification

`cargo check --workspace` and `cargo test --workspace --lib --bins`
both clean on hero_rpc; `cargo test -p hero_rpc2 --features uds-http`
also green (incl. the new `http_well_known` tests).
`example/recipe_server` builds end-to-end against the local in-tree
patches.

Two pre-existing test failures on `development` (`hero_rpc_derive`'s
`sse_proxy` integration test missing a `herolib_core` crate ref, and
two `hero_rpc_osis` examples calling stale APIs) are untouched here —
not caused by #90; they need their own fixes outside this PR.

## What's NOT changed (deferred to Phase 2-4)

* hero_service / hero_logic / hero_compute / hero_db service binaries
  (Phase 2 + 3, one PR per repo).
* hero_launcher — its scaffolded SDK consumed by hero_wasmos —
  migrated in a companion branch per the design-comment thread.
timur merged commit 51c306ed84 into development 2026-05-20 23:00:40 +00:00
Sign in to join this conversation.
No reviewers
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!97
No description provided.