LearnNewsExamplesServices
Frontmatter
id17252
titleComposed-server brokered poll-digest for the browser wake consumer
stateClosed
labels
enhancementaiarchitecture
assigneesneo-fable-clio
createdAtAug 16, 2026, 10:19 PM
updatedAtAug 17, 2026, 12:47 AM
githubUrlhttps://github.com/neomjs/neo/issues/17252
authorneo-fable-clio
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 17, 2026, 12:46 AM

Composed-server brokered poll-digest for the browser wake consumer

Closed Backlog/active-chunk-16 enhancementaiarchitecture
neo-fable-clio
neo-fable-clio commented on Aug 16, 2026, 10:19 PM

Composed-server brokered poll-digest for the browser wake consumer

Context

#17130 leg 2 (the cockpit's store-bound wake rendering) surfaced a topology fact at build time: the browser consumer's pollDigest seam — the catch-up truth lane the frozen slice-2/slice-3 wire names ("poll-digest {subscriptionId, sinceLogId} fires once per connection") — has no reachable implementation in the direct-browser topology. The seam exists, the consumer honors it, the cockpit passes it through (wakePollDigest), and nothing in the deployed browser path can supply it.

The Problem

Verified this session (V-B-A, all read-only):

  • manage_wake_subscription {action: 'poll-digest'} is an authenticated MC-plane callWakeSubscriptionService.pollDigest throws unboundIdentityError without a bound caller (ai/services/memory-core/WakeSubscriptionService.mjs:1594).
  • The browser page holds no plane credential by design: both mints live in the registry bridge's closures (apps/agentos/fleet/installFleetBridge.mjs — Option-D custody), so the cockpit cannot build an MC-authenticated poll itself without breaking custody.
  • The composed fleet server exposes /wake, /fleet/probe, /fleet/events, POST /fleet (ai/services/fleet/fleetServer.mjs) — no viewer-facing digest-poll surface, and the wire-verb twin lists (fleetWireMethods.mjs) carry no digest verb.
  • The relay topology is fine: devFleetServer.mjs:168 wires pollDigest through its proven plane client. Only the browser half is unreachable.

Consequence: a cold-started or reconnecting browser viewer receives new pushes but cannot drain pending wakes — #17130's "cold start drains pending wakes from the vouched handshake id alone" AC is client-unreachable until a server surface exists. The client side ships honest absence (the telltale renders catch-up: no observation), which is correct and insufficient.

The Architectural Reality

The composed server already brokers viewer-credentialed MC calls: connect-time arming (fleetServer.mjs /fleet/events handler) takes the viewer's class-3 mint from x-neo-mc-authorization, builds an in-flight MC client with the viewer's own authority, and never persists the credential. Poll-digest is the SAME credential class and the same in-flight lifetime — the pattern exists, only the second consumer of it is missing.

The Fix

  1. Server: a sibling endpoint on the events origin — e.g. POST /fleet/events/digest — taking exactly the stream's two headers (class-1 admission on Authorization, class-3 on x-neo-mc-authorization), running manage_wake_subscription {action: 'poll-digest', subscriptionId, sinceLogId} through the same in-flight viewer-credentialed context the arming path builds, and returning the digest result as a wire envelope. Byte-identical pairs refused exactly like arming. No change to any existing frame or verb — additive sibling, wire twins untouched.
  2. Client: openWakeStream (the bridge capability) gains an internal default pollDigest built from the SAME pinned fetchImpl + header closure it already owns — zero cockpit change (FleetCockpit.wakePollDigest stays the test-injection override; the capability default only engages when no explicit seam is supplied). The consumer's existing catch-up mechanics (fleetWakeStreamConsumer.mjs — cold drain from the vouched id, watermark echo, fresh ≠ empty ≠ failed) light up unchanged.
  3. Evidence: extend the FleetCockpitViewerWakeNL e2e (shipped in #17130 leg 2 with the production fan-out fixture) with the digest-poll leg — the fixture answers the sibling endpoint, and the cold-drain journey closes end-to-end in the page.

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
POST /fleet/events/digest (new) ai/services/fleet/fleetServer.mjs (sibling of /fleet/events) viewer-credentialed MC poll-digest, brokered in-flight absent class-3 header → honest refusal envelope (not-armed vocabulary) endpoint JSDoc + #16741-family notes new unit + e2e digest leg
openWakeStream capability default pollDigest apps/agentos/fleet/installFleetBridge.mjs closure-built default against the sibling endpoint; explicit observational pollDigest option still overrides no endpoint (older server) → the consumer's honest failed catch-up observation carrying the endpoint-absent reason (per amended AC 4) capability JSDoc installFleetBridge.spec.mjs extension

Decision Record impact

aligned-with the FM client topology ADR (remote-only journey; custodian shapes) — the same record #17130 builds against. Additive to the frozen slice-2/slice-3 wire: no existing frame, header, or verb changes.

Acceptance Criteria

  • A browser viewer with both mints in closure custody drains pending wakes on cold start from the vouched handshake id alone — proven in the page against the composed server (e2e digest leg).
  • The endpoint refuses byte-identical class-1/class-3 pairs and absent class-3 with the established not-armed vocabulary — never a fabricated drain.
  • The viewer credential is used in-flight only (arming-path parity); nothing persists server-side, and the client-held watermark stays client-held.
  • An older server without the endpoint lands as the consumer's honest failed catch-up observation carrying the endpoint-absent reason — once per connection, bounded, no retry storm, never a fabricated drain. (Amended 2026-08-16 pre-PR: failed-with-reason is the truthful observation — a poll WAS attempted and refused; rendering that as absence would hide a real signal. The absence state stays reserved for genuinely unwired seams.)
  • #17130's residual cold-drain AC clause is closed by reference from this ticket.

Out of Scope

  • Relay-side catch-up (devFleetServer — already wired through the plane client).
  • Wake delivery over the ingress for host-listener-less clients (#16741).
  • Any change to the SSE frame grammar or the wire-verb twin lists.

Avoided Traps

  • A wire verb on POST /fleet: would extend the class-3 credential surface onto the general wire POST and mutate both frozen verb twins; the events-origin sibling keeps the push lane's credential shape exactly where it already lives.
  • Page-side MC client: breaks Option-D custody (mints would need to reach the page realm) — rejected outright.
  • Server-side drain-on-connect (pushing pending as wake frames at arming): duplicates derive-at-read into the push lane and inverts "push is latency, poll is truth".

Related

#17130 (the client half + the seam this closes) · #16742 (C1 custody) · #16741 (ingress delivery, different clients) · PR #17194 (leg 1 consumer) · epic #16168.

Live latest-open sweep: checked latest 20 open issues at 2026-08-16T20:19Z, no equivalent; A2A in-flight claim sweep (last hour, all read-states) clean — active claims are npmignore/who_is_online/theme lanes, no overlap.

Origin Session ID: 71baabc5-3ebe-46ff-99ce-a301e78cb7c5

Retrieval Hint: query_raw_memories("browser poll-digest brokered composed server viewer credential events sibling endpoint")

tobiu referenced in commit ff2ea5e - "feat(ai): brokered viewer poll-digest on the events origin (#17252) (#17262)" on Aug 17, 2026, 12:46 AM
tobiu closed this issue on Aug 17, 2026, 12:46 AM