Skip to content

Commit dfadbcd

Browse files
committed
docs: record the REST executor target (B1) — arago HTTP-callout, gated
rs-graph-llm graph-flow-action-ogar::rest::RestExecutor (feature = "rest", ureq) POSTs bound params to an HTTP endpoint and returns the response as resultParameters — the arago HTTP-callout handler shape, run only behind the hard gate. Completes the executor family alongside native; SSH/WinRM remain. - ARAGO-ACTIONHANDLER-PARITY: B1 §3 bullet (REST shipped), executor scorecard row split (REST SHIPPED / SSH+WinRM remaining), verdict, cross-ref to rest.rs. - DISCOVERY-MAP: D-ACTIONHANDLER-REST (G / CODED). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYvNjD8M8LMNYbRy3gq2FP
1 parent 89d421c commit dfadbcd

2 files changed

Lines changed: 23 additions & 11 deletions

File tree

docs/ARAGO-ACTIONHANDLER-PARITY.md

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,13 @@ downstream. The remaining bricks:
190190
**native target is SHIPPED**: `ogar-action-handler::NativeCommandExecutor` runs
191191
`ExecuteCommand` via a local POSIX shell and returns `output`/`stderr`/`exitcode`
192192
— proven end-to-end by `full_dispatch_runs_a_real_command` ("OGAR running it
193-
here," native). SSH / REST / WinRM targets follow the same trait; rs-graph-llm's
194-
`graph-flow-action` provides the production executors (and runs `commit_via`).
193+
here," native). The **REST target is SHIPPED too**: rs-graph-llm
194+
`graph-flow-action-ogar::rest::RestExecutor` (`feature = "rest"`, pure-Rust
195+
`ureq`) POSTs the bound params to an HTTP endpoint and returns the response as
196+
`resultParameters` — the arago HTTP-callout shape — and runs only behind the
197+
gate (`rest_executor_runs_only_behind_the_gate`). SSH / WinRM follow the same
198+
`CapabilityExecutor` trait (SSH = arago's canonical `ExecuteCommand`-over-SSH);
199+
rs-graph-llm hosts the production executors (the gate runs `commit_via`).
195200
- **B1-uplink — the hard gate before the executor (SHIPPED).** rs-graph-llm's
196201
`graph-flow-action-ogar` crate is the seam: `GatedOgarHandler` wraps an OGAR
197202
`CapabilityExecutor` as a `graph-flow-action::ActionHandler`, so the executor's
@@ -254,7 +259,8 @@ transport over them.
254259
| **Reactive dispatch + B1 seam** |`[G]` SHIPPED | `action_ws::handle_submit` + the `CapabilityExecutor` trait (validate→ack→bind→execute→result; tested with a mock) |
255260
| **Executor — native target (B1)** |`[G]` SHIPPED | `ogar-action-handler::NativeCommandExecutor` runs `ExecuteCommand` for real; `full_dispatch_runs_a_real_command` |
256261
| **Hard gate before executor (B1-uplink)** |`[G]` SHIPPED | rs-graph-llm `graph-flow-action-ogar::GatedOgarHandler``commit_via` (RBAC ∧ guard ∧ MUL) lands before `handle`; `take_result()` is `None` iff the gate refused (3 tests) |
257-
| **Executor — SSH/REST/WinRM (B1)** |`[H]` | further `CapabilityExecutor` impls (rs-graph-llm `graph-flow-action`) |
262+
| **Executor — REST target (B1)** |`[G]` SHIPPED | rs-graph-llm `graph-flow-action-ogar::rest::RestExecutor` (`feature = "rest"`, ureq) POSTs bound params → resultParameters; runs only behind the gate (`rest_executor_runs_only_behind_the_gate`) |
263+
| **Executor — SSH/WinRM (B1)** |`[H]` | further `CapabilityExecutor` impls (SSH = arago's canonical `ExecuteCommand`-over-SSH; needs an SSH client + a live host to test) |
258264
| **Live transport — daemon core + WebSocket (B2-transport)** |`[G]` SHIPPED | rs-graph-llm `graph-flow-action-ogar::daemon`: transport-agnostic `Daemon::react`/`serve` + `Transport` trait + `WsTransport` (action-ws), gate-driving; mock-server roundtrip. `Auth` ← OGIT `NTO/Auth/Configuration` |
259265
| **Live transport — Kafka edge (B2-transport)** |`[H]` | `rdkafka` over the same `Transport` trait (action topic → result topic); core ready, needs the topic/record shape pinned |
260266
| **Instance config lift — capabilities (B2-lift)** |`[G]` SHIPPED | `registration::lift_registration` + `ogar-action-handler::parse_capabilities`: real `GET /capabilities` JSON → `ConcreteCapability` (`ActionParam[]`); `rest_registration_lifts_binds_and_runs` (JSON → lift → bind → run) |
@@ -274,14 +280,17 @@ end-to-end, `rest_registration_lifts_binds_and_runs`) and per-handler `StateGuar
274280
sets (`rest_applicabilities_lift_to_per_handler_guards`). And the **live daemon
275281
runs over a real socket**`graph-flow-action-ogar::daemon` drives the gated
276282
dispatch through a `Transport` trait, with the `action-ws` WebSocket edge proven
277-
by a mock-server roundtrip. What's left for a **live** drop-in replacement of
278-
arago's Python daemon: the **Kafka transport edge** (HIRO's internal bus —
279-
`rdkafka` over the same `Transport` trait, needs the topic/record shape pinned)
280-
and the **non-native executor targets** (SSH/REST). Each is a single edge/runner
281-
impl over existing types — **no missing IR, no missing protocol mapping**. That is
282-
the honest state: OGAR *is* an ActionHandler that reads its own registration,
283-
gates every action, runs commands, and speaks `action-ws` over a live socket;
284-
a Kafka consumer away from HIRO's internal bus.
283+
by a mock-server roundtrip. Two executor targets run gated — **native** (local
284+
command) and **REST** (HTTP callout). What's left for a **live** drop-in
285+
replacement of arago's Python daemon: the **Kafka transport edge** (HIRO's
286+
internal bus — `rdkafka` over the same `Transport` trait, needs the topic/record
287+
shape pinned) and the **SSH executor** (arago's canonical `ExecuteCommand`-over-SSH
288+
— an SSH client over the same `CapabilityExecutor` trait, needs a live host to
289+
test). Each is a single edge/runner impl over existing types — **no missing IR,
290+
no missing protocol mapping**. That is the honest state: OGAR *is* an ActionHandler
291+
that reads its own registration, gates every action, runs commands and HTTP
292+
callouts, and speaks `action-ws` over a live socket; a Kafka consumer + an SSH
293+
runner away from being arago's Python daemon, on any HIRO deployment.
285294

286295
---
287296

@@ -318,6 +327,8 @@ is replaceable; the parity claim is certified, not argued.
318327
- `rs-graph-llm/graph-flow-action-ogar/src/daemon.rs`**B2-transport**: the
319328
transport-agnostic `Daemon` (`react`/`serve`) + the `Transport` trait +
320329
`WsTransport` (action-ws WebSocket edge) + the OGIT-`Auth`-derived identity.
330+
- `rs-graph-llm/graph-flow-action-ogar/src/rest.rs` — the **REST executor**
331+
(`RestExecutor`, `feature = "rest"`): the arago HTTP-callout target, gated.
321332
- arago: `github.com/arago/ActionHandlers`,
322333
`arago/python-hiro-stonebranch-actionhandler`, HIRO 7 Action API tutorial.
323334
- **HIRO 7 Action API machine-readable specs (the authoritative harvest, §2a):**

docs/DISCOVERY-MAP.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ two halves of a cell. ADR‑026 names the cascade that ties them.
214214
| D‑ACTIONHANDLER‑UPLINK | The hard gate wired to the OGAR executor (cross‑repo seam): rs‑graph‑llm `graph-flow-action-ogar::GatedOgarHandler` wraps an OGAR `CapabilityExecutor` as a `graph-flow-action::ActionHandler`, so `dispatch_via`'s cold floor (`commit_via`: def‑match → RBAC `ClassRbac` → `StateGuard` → MUL) lands **before** the executor's `handle`. Structural proof the contract lands first: `take_result()`/`run_gated` returns `None` whenever the gate refused — unauthorized actor → `Denied` (executor never runs), MUL `Block` → `Escalated` (executor never runs); only the authorized path reaches `NativeCommandExecutor` and runs the real command (3 tests). Dependency hygiene held: `graph-flow-action` stays contract‑only (`I‑ACTIONHANDLER‑IS‑KGV‑NOT‑CHOKEPOINT`); `ogar-from-schema` carries no `lance-graph` dep — the two sides meet only at this crate's API (one `lance-graph-contract`). rs‑graph‑llm pinned to toolchain 1.95.0 to match the AdaWorldAPI stack | G | CODED | `rs-graph-llm/graph-flow-action-ogar/src/lib.rs` | D‑ACTIONHANDLER‑PARITY |
215215
| D‑ACTIONHANDLER‑B2LIFT | REST registration **instance lift** (B2-lift) — turns a deployed handler's `GET /capabilities` JSON (`MapOfCapabilities`) into the concrete signatures the *schema* half can't supply: `registration::{RegisteredCapability,ModelFilter}` (typed DTOs, `Deserialize` behind the `serde` feature) + the pure lift `lift_registration → ConcreteCapability` (concrete `ActionParam[]` with `(name,mandatory,default)`) and `model_filter_to_guard` (arago `ModelFilter{Var,Mode,Value}`→`KausalSpec::StateGuard`, field‑for‑field). Producer stays parser‑free; the runtime `ogar-action-handler::parse_capabilities` does the `serde_json` read (producer‑defines‑types / runtime‑does‑I/O split). Proven end‑to‑end: `rest_registration_lifts_binds_and_runs` (real JSON → lift → `bind_parameters` → `NativeCommandExecutor` runs the command). Remaining: the `GET /applicabilities` `MapOfApplicabilities` envelope read (the `ModelFilter→StateGuard` lift is done). **CORRECTION (canon‑pass 2026‑06‑24): applicabilities envelope now SHIPPED** — `registration::{RegisteredApplicability,lift_applicabilities}` + `ogar-action-handler::parse_applicabilities` lift a real `GET /applicabilities` JSON body into per‑handler `StateGuard` sets (`rest_applicabilities_lift_to_per_handler_guards`); inner filter‑list field name alias‑flexible (`modelFilters`/`model`/`filters`) pending a live response. Supersedes the "Remaining" note | G | CODED | `ogar-from-schema/src/registration.rs`, `ogar-action-handler/src/lib.rs` | D‑ACTIONHANDLER‑PARITY |
216216
| D‑ACTIONHANDLER‑TRANSPORT | The live action daemon (B2-transport), **transport-agnostic** by construction: rs‑graph‑llm `graph-flow-action-ogar::daemon::Daemon::react` turns one inbound `action-ws` JSON frame into the outbound frames it warrants (ack + `sendActionResult`, or nack), running the hard gate (`run_gated`) + executor in between — pure, no I/O. A `Transport` trait (`recv`/`send`) is the swappable edge; `Daemon::serve` is the loop; both the WebSocket and a future Kafka edge share it verbatim (HIRO distributes actions over BOTH wires — the wire differs, the dispatch doesn't). The `WsTransport` action-ws edge (`feature = "ws"`, tokio-tungstenite) presents the `token-$TOKEN` subprotocol and is proven by `ws_roundtrip_against_a_mock_server` (engine submitAction → ack → real command → result over a socket). Connection identity is an `Auth` type shaped after OGIT `NTO/Auth/Configuration` (`auth_store` 0x0B01): the principal the transport authenticates as (`accountId`) IS the actor the gate authorizes. Remaining: the Kafka edge (`rdkafka` over the same trait — core ready, needs topic/record shape) and SSH/REST executors | G (core + ws edge) / H (kafka edge) | CODED | `rs-graph-llm/graph-flow-action-ogar/src/daemon.rs` | D‑ACTIONHANDLER‑UPLINK, D‑ACTIONHANDLER‑B2LIFT |
217+
| D‑ACTIONHANDLER‑REST | REST executor target (B1) — the arago HTTP-callout handler shape: rs‑graph‑llm `graph-flow-action-ogar::rest::RestExecutor` (`feature = "rest"`, pure-Rust `ureq`, sync — fits the sync `CapabilityExecutor` trait) POSTs the bound params as a JSON body to a configured endpoint, returns the response `status`+`body` as `resultParameters`. Any completed HTTP response (incl. 4xx/5xx) is `resultParameters`; only a transport failure is an executor `Err` (mirrors arago reporting the callee's response). `Clone` (ureq Agent is Arc-backed) ⟹ composes into `Daemon`/`run_gated` as a gated route. Proven: `posts_params_and_returns_status_and_body` (mock HTTP) + `rest_executor_runs_only_behind_the_gate` (authorized → REST call fires; unauthorized → `Denied`, endpoint never hit). Completes the executor family with native; SSH/WinRM remain | G | CODED | `rs-graph-llm/graph-flow-action-ogar/src/rest.rs` | D‑ACTIONHANDLER‑UPLINK |
217218
| D‑OSM | `ogar-from-osm-pbf` — Node/Way/Relation; quadkey NiblePath from resolved geometry | H | IDEA | (queued) | D‑VOCAB, `[per rt]` D‑OSM‑3 |
218219
| D‑PATTERN | `ogar-pattern` — recognition library + confidence (FMA‑D/FIBO/SKR/PROV‑O) | H | IDEA | (queued) | D‑TTL |
219220
| D‑ACTION | `ogar-actionable` — lifecycle → `ActionDef`/`KausalSpec` | H | IDEA | (queued) | D‑PATTERN |

0 commit comments

Comments
 (0)