You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .claude/board/EPIPHANIES.md
+40Lines changed: 40 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,46 @@
7
7
8
8
---
9
9
10
+
## 2026-06-24 — E-ACTIONHANDLER-TRANSPORT — the daemon is transport-agnostic because HIRO is multi-wire; and the OGIT Auth type unifies "who connects" with "who the gate authorizes"
11
+
12
+
**Status:** FINDING (`[G]` for the core + WebSocket edge; `[H]` for the Kafka edge).
13
+
14
+
Two design facts surfaced building B2-transport (the live action daemon, in
15
+
rs-graph-llm `graph-flow-action-ogar::daemon`):
16
+
17
+
1.**HIRO distributes actions over more than one wire** — a handler-facing
18
+
WebSocket (`action-ws`) AND an internal Kafka bus that legacy handlers consume
19
+
directly (operator note, 2026-06-24). The wire differs; the dispatch doesn't.
20
+
So the daemon is factored as: `Daemon::react` (the transport-agnostic core —
21
+
one inbound `action-ws` frame → outbound frames, running the gate + executor,
22
+
pure/no-I/O) + a `Transport` trait (`recv`/`send`, the swappable edge) +
23
+
`Daemon::serve` (the loop, generic over `Transport`). The WebSocket edge
24
+
(`WsTransport`) and a future Kafka edge (`rdkafka`) share `serve` verbatim —
25
+
the gated dispatch is written once, the wire is a thin shell. This is the
26
+
action-arm analogue of the codec stack's "one algebra, many carriers": one
27
+
dispatch, many transports.
28
+
29
+
2.**The OGIT Auth type unifies the two identities that must be the same.** A
30
+
handler's connection presents a credential; the gate authorizes an actor.
31
+
These MUST be the same principal — and OGIT's `NTO/Auth/Configuration` (the
32
+
`auth_store` class, OGAR `0x0B01`) already unifies them: it is keyed by
33
+
`accountId` and maps `sub` → actor (`0x0104`), org/tenant → scope. So the
34
+
daemon's `Auth` type is shaped after it: one value carries the `token` the
35
+
transport presents (the `token-$TOKEN` subprotocol) AND the `account` the gate
36
+
authorizes as (`accountId` → actor). `Daemon::new` takes `&Auth` and derives
37
+
the gate actor from `auth.account`; `WsTransport::connect` takes `&Auth` and
38
+
presents `auth.token`. The identity that connects IS the identity the RBAC
39
+
grant is checked against — structurally, not by convention. (A future
40
+
producer-side `auth_from_ogit(entity)` lift would populate `Auth` from a real
41
+
`NTO/Auth/Configuration` node, the same way `assemble_action_handler` lifts the
42
+
handler contract.)
43
+
44
+
Proven by `ws_roundtrip_against_a_mock_server` (engine `submitAction` → ack → real
45
+
command → result over a live socket) + 10 pure-core tests. Scorecard: B2-transport
## 2026-06-24 — E-ACTIONHANDLER-B2LIFT — the producer stays parser-free even when lifting a JSON REST response: it defines the `Deserialize` DTOs + the pure lift, the runtime does the `from_str`
11
51
12
52
**Status:** FINDING (`[G]` for capabilities; `[H]` for the applicabilities envelope).
|**Executor — SSH target (B1)**| 🟡 `[G]` code / `[H]` live |`ogar-action-handler::SshExecutor` shells out to system `ssh` (non-interactive `BatchMode=yes`, same `output`/`stderr`/`exitcode` shape as native) — arago's canonical `ExecuteCommand`-over-SSH, dep-free. argv construction + pre-spawn guards tested; end-to-end needs a live host (no sshd in CI) |
269
+
|**Executor — WinRM (B1)**| ⛔ `[H]`| a further `CapabilityExecutor` impl (Windows remote exec) |
|**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 |
0 commit comments