# Realtime Client Capability — Platform Upstream Decision

**Date:** 2026-08-19  
**Status:** Decision complete; upstream `platform-modules/mod` capability required before final AWP realtime client implementation.  
**Architecture context:** Realtime follows the canonical `browser -> edge/gateway -> control plane` topology. Realtime transport is never authoritative lifecycle state.

## 1. Question

AWP needs one centralized browser realtime layer rather than one WebSocket/SSE connection per page/widget. Generic mechanics include:

- shared connection ownership;
- reconnect/backoff;
- subscription registration;
- frame fan-out;
- optional multiplex/demultiplex;
- connection lifecycle/status;
- send through the managed connection.

Where should the reusable browser/client mechanics live?

1. AWP host code;
2. a new standalone Platform module;
3. a capability inside the existing Platform realtime family.

## 2. Decision

Generic realtime-client mechanics belong inside the existing Platform realtime family, not as an AWP-local infrastructure copy and not as a separate bounded-context package.

Recommended shape:

```text
@platform-modules/realtime/client
  framework-neutral client connection manager

@platform-modules/realtime-react
  thin React binding over the client manager
```

Exact export names remain an upstream `mod` spec decision.

## 3. Why this survives the reuse/delete test

Without a reusable client capability, each realtime consumer has to rebuild:

```text
connection registry
subscriber registry
reconnect/backoff
connection lifecycle
frame distribution
resource cleanup
```

Those are generic correctness mechanics, not AWP product semantics.

A separate `@platform-modules/realtime-client` package would add package/semver/dependency surface without representing another domain. Therefore it belongs as an importable capability under the existing realtime Module.

## 4. Platform owns

Only generic client mechanics:

```text
connection manager
connection reuse
subscription registry
frame fan-out
bounded reconnect/backoff/jitter
connection status/lifecycle
clean connect/disconnect/reference counting
transport send
framework-neutral client contract
React context/hook binding
```

Platform does **not** own AWP event vocabulary, authorization, lifecycle state or gateway/control-plane topology.

## 5. AWP owns

```text
AWP realtime event-type union
Project/Plan/WorkItem/FactoryRun/AgentRun/CI/etc scopes
subscription authorization
which durable business events produce realtime projections
read-model invalidation/refetch behavior
screen stale/fresh semantics
business-event cursor/version semantics
Attention/Approval/Incident reactions
public realtime endpoint contract
gateway fan-out/proxy mechanics
control-plane projection source
reconnect recovery semantics from authoritative state
```

Notification state is not Approval state. Realtime frames are not durable business events.

## 6. Three-plane realtime path

Canonical flow:

```text
PostgreSQL / authoritative AWP state
          |
          v
control-plane business events/read models
          |
          v
realtime projection stream
          |
          v
edge/gateway fan-out endpoint
          |
          v
Platform realtime client manager
          |
          v
React/AWP UI
```

Rules:

```text
browser -X-> PostgreSQL
browser -X-> Kubernetes
browser -X-> DBOS

gateway realtime connection state != product truth
control-plane state remains recoverable without an active realtime connection
reconnect performs cursor/refetch/state recovery rather than trusting missed frames
```

The public realtime transport may later use an edge/vendor-specific fan-out implementation, but vendor-specific APIs remain gateway adapters and do not enter Platform's generic client contract or AWP domain code.

## 7. Authentication and authorization

The gateway may authenticate the public connection and reject invalid credentials. Final subscription authorization remains a control-plane/product-policy concern.

Do not encode final AWP authorization inside the generic Platform client manager.

Connection/subscription requests need enough authenticated context to let the gateway/control-plane path enforce scope authorization without trusting arbitrary client-provided scope IDs.

## 8. Required upstream `platform-modules/mod` sequence

1. Amend the realtime boundary/design spec.
2. Run/fill the module-plan gates for the capability.
3. Amend canonical registry/docs in the same logical change.
4. Add framework-neutral realtime client capability inside the realtime package.
5. Adapt `realtime-react` to bind the generic client.
6. Add behavioral tests for connection sharing, reconnect/backoff, cleanup, subscription fan-out and failure paths.
7. Extend the consumer harness so a broken export fails consumption.
8. Run real typecheck separately from tests.
9. Run seam review against the accepted boundary.
10. Merge/publish the upstream change.
11. Pin/consume the exact package version in AWP.

## 9. AWP rule until upstream lands

Do not create a permanent AWP-only shared socket manager that duplicates the generic capability.

A temporary spike is permitted only to prove the upstream seam and must keep:

```text
generic connection mechanics separable
AWP event/policy semantics separate
gateway transport concerns separate
control-plane truth separate
```

## 10. Final disposition

```text
New standalone Platform module?     NO
New Platform capability?            YES
Existing family?                    @platform-modules/realtime
Framework binding?                  @platform-modules/realtime-react
AWP-only generic socket manager?    NO
Public browser endpoint?            EDGE/GATEWAY PLANE
Authoritative realtime source?      CONTROL-PLANE STATE/EVENTS
mod spec/code change required?      YES
AWP-specific realtime policy?       STAYS IN AWP
```
