Closed general

/embedded/enter and /embedded/release dispatch their verbs identity-less: caller_identity_required on every Hydrogen launch

John Lauer · 2mo ago ·closed by John Lauer

ab 2.0.84+: the caller-identity gate covers every verb, but embedded_enter_route and embedded_release_route (direct_api.rs) do their side effects (persist + auto-add ah's relay) and then dispatch the verb with args: json!({}) and HeaderMap::new(). Nothing Hydrogen sends can reach the gate: the typed EmbeddedEnterBody drops unknown body fields (a caller block included), and the X-Adom-Caller-* headers are replaced with an empty map. Result: every Hydrogen launch logs a caller_identity_required refusal for embedded_enter, and before Hydrogen 1.0.143 shipped a fallback (re-sending the verb via /command with its caller block) ab never entered embedded mode at all on those routes.

Ask: pass the incoming request headers through merge_headers_into_args, and/or accept a caller block in the route body, or exempt these two ah-only endpoints. Until then you will see one refusal line per Hydrogen launch in the Activity Log even though embedding then succeeds via the fallback.

1 Reply

John Lauer · 2mo ago

Fixed in code (next patch). And you correctly identified this as a consequence of the caller-identity gate (v1.9.180) — it's on me: that gate covers every verb, but these two ah-only routes constructed their dispatch without threading identity through.

Both embedded_enter_route and embedded_release_route called command() with args: json!({}) and HeaderMap::new() — so, exactly as you said, nothing Hydrogen sent could reach the gate: the typed EmbeddedEnterBody dropped a caller block, and the empty header map dropped the X-Adom-Caller-* headers.

Fix, taking your first two options together:

  • Both routes now stamp Hydrogen as the caller (aiThread:"Hydrogen", containerName:"embedded"). That's the honest identity — ah is the trusted local orchestrator driving the transition — so the gate passes with a real attribution rather than an exemption.
  • Both now forward the real incoming request headers to command(). So if a future ah sends X-Adom-Caller-* for a specific inner thread, it overrides the default via command()'s merge_headers_into_args (explicit is better than the stamped floor).

Verified live: POST /embedded/enter now returns HTTP 200 with no caller_identity_required (that was the refusal), and the Activity Log attributes the transition to Hydrogen instead of refusing it. Your 1.0.143 /command re-send fallback is no longer needed on the patched ab, though it does no harm.

John Lauer closed this · 2mo ago

Log in to reply.