Skip to content

Latest commit

 

History

History
320 lines (222 loc) · 11.4 KB

File metadata and controls

320 lines (222 loc) · 11.4 KB

Client State Machine

This document describes the client-visible state machine for the C1 channel.

  • MVP-faithful: every state and transition exists in a running system.
  • Informative, not normative: it explains one concrete UI realization built on top of the normative contracts:

The authoritative protocol and API guarantees live in those two contracts. This document focuses on how a client UI stitches them together into a deterministic user flow.


1. TL;DR (60-second read)

  • The client UX is modeled as a single-session funnel:
    • Input → Topic selection → Topic result
  • All analysis and entitlement are scoped to (sessionId, topic):
    • sessionId comes from POST /api/session
    • topic is chosen by the user on the topic selection step
  • Visibility of results is controlled by stream events:
    • analysisChunk / response deliver content
    • paywall interrupts visibility
    • unlock delivers post-entitlement access to the full result (stream does not resume)
  • Session lifetime:
    • Backend sessions have a finite TTL (implementation-defined)
    • After TTL, any navigation using that sessionId is treated as SessionExpired

The Mermaid diagram in ../diagrams/client_state_machine.mmd is the canonical visual reference; this document binds each node to actual UI behavior and stream semantics.


2. State Inventory

The diagram defines the following conceptual UI states:

  • Idle
  • EditingInput
  • SessionCreated
  • TopicSelection
  • Requesting
  • Loading
  • Preview
  • Full
  • Streaming
  • PaymentPending
  • Paid
  • SessionExpired

In the MVP, these concepts are realized across three UI surfaces:

  • Input surface (collects user input and creates a session)
  • Topic selection surface (lets user pick topic under a given sessionId)
  • Result surface (connects to stream and renders delivery / paywall / unlock)

On the result surface, an internal UI flag may track finer-grained view states such as: connecting, streaming, paywalled, waiting, completed, error. This is implementation detail; the diagram states remain the conceptual source of truth.


3. Onboarding: Idle → EditingInput → SessionCreated

3.1 Idle

Meaning

  • No session exists yet.
  • User has not started editing input.

Typical UI representation

  • User is on the input surface; fields are empty or untouched.

Entry

  • User opens the product URL.

Exit

  • Idle → EditingInput when the user begins interacting with the input surface.

3.2 EditingInput

Meaning

  • User is actively editing the analysis input for a prospective session.

Typical UI representation

  • User is still on the input surface with local form state being edited.

Exit

  • EditingInput → SessionCreated on “submit input”:
    • Client performs client-side validation (implementation-defined).
    • Client calls POST /api/session (see rest_api_contract.md).
    • On success, backend returns { sessionId }.
    • Client navigates to the topic selection surface.

Errors during validation or session creation keep the client in EditingInput with inline error UX (these generic error paths are intentionally not modeled in the primary diagram).

3.3 SessionCreated

Meaning

  • A session exists server-side; the client holds a sessionId, but the user has not chosen a topic yet.

Typical UI representation

  • A navigation transition occurs to the topic selection surface.

Exit

  • SessionCreated → TopicSelection when the topic selection surface is rendered.

4. TopicSelection and Topic-scoped Entitlement

4.1 TopicSelection

Meaning

  • User chooses which logical topic to analyze under the current session.

Typical UI representation

  • The topic selection surface shows a fixed list of topics.

Entry

  • From SessionCreated, or returning from a result state (Full → TopicSelection or Preview → TopicSelection).

Exit

  • TopicSelection → Requesting on “select topic / open analysis”:

    • Client navigates to the result surface for (sessionId, topic).
  • TopicSelection → SessionExpired if the backend TTL has elapsed and the session no longer exists.

4.2 Entitlement scope: sessionId + topic

Contract view

  • There is no user account concept in C1.
  • Entitlement is expressed as: “Is this (sessionId, topic) entitled to full visibility?”

This aligns with the C1 overview and the stream semantics (paywall / unlock). See:


5. Result Surface: Requesting → Loading → Preview / Full

The result surface connects to the stream, requests analysis for (sessionId, topic), and renders content according to stream_protocol.md.

5.1 Requesting

Meaning

  • Client has requested analysis for (sessionId, topic) and is awaiting stream events.

Typical UI representation

  • Result surface is mounted and begins connecting to the stream delivery channel.

Exit

  • Requesting → Loading when the backend accepts the request and begins execution.
    • (In practice, the UI may move quickly to Streaming once the first analysisChunk arrives.)

5.2 Loading

Meaning

  • Execution is in progress, but the client has not yet determined whether the visibility path will be Preview or Full.

How the path is determined

  • The first content-bearing events determine the path:
    • If the topic is free or already entitled, the client is effectively on the Full path.
    • If the topic requires entitlement and is not yet entitled, the client is on the Preview path that terminates in a paywall event.

Exit

  • Loading → Preview when policy requires upgrade / entitlement.
  • Loading → Full when policy allows full visibility.

5.3 Preview

Meaning

  • Client shows a bounded preview of the analysis plus a call-to-action to unlock.

Stream semantics

  • Two MVP-consistent ways to reach Preview:
    • Live streaming (first-time paid topic):
      receive analysisChunk up to a bounded fraction, then a paywall that stops further content.
    • Cached non-stream (previously computed result available):
      a truncated response with needPayment=true, immediately followed by a paywall (no further content events for this request; see stream_protocol.md).

Exit

  • Preview → PaymentPending on “click unlock”:

    • Client calls POST /api/checkout (see rest_api_contract.md).
    • Browser is redirected to an external checkout page (payment provider).
  • Preview → TopicSelection on “choose another topic”.

  • Preview → SessionExpired when backend TTL is exceeded and subsequent operations fail.


6. Payment Flow: PaymentPending → Paid

6.1 PaymentPending

Meaning

  • User is completing payment on the provider’s checkout page; the client is temporarily not in control of the screen.

Contract-level behavior

  • Client initiates checkout via POST /api/checkout.
  • The payment provider notifies the backend via POST /api/webhook (not a client call). (See rest_api_contract.md.)

Exit

  • PaymentPending → Paid on successful payment completion and entitlement being recorded.
  • PaymentPending → Preview on canceled/failed payment (no entitlement recorded).

6.2 Unlock and waiting

Meaning

  • Payment succeeded; the client is entitled to full visibility.
  • If the full result is not yet materialized, the client may enter a “waiting for full result” view.

Stream semantics

  • unlock is emitted after entitlement is granted.
    • If unlock carries content, this is terminal success.
    • If unlock(waiting=true) is emitted, the client should retry retrieval until response arrives (see stream_protocol.md).

Waiting is an informative UI hint; clients should treat unlock as terminal and rely on session/stream retry semantics as defined in the stream protocol.

6.3 Paid

Meaning

  • Backend has recorded entitlement for (sessionId, topic).

Behavior

  • Subsequent requests for the same (sessionId, topic) should no longer produce a paywall.
  • After entitlement is granted, full-result delivery takes one of two forms:
    • A terminal response (cached/already-entitled or replay path).
    • A one-time unlock carrying full content for the user who just paid (post-paywall path; stream does not resume).

7. Streaming Path: Full and Streaming

7.1 Full (non-streamed)

Meaning

  • Client has access to the full result; content arrives as a single terminal event.

Stream semantics

Exit

  • Full → TopicSelection on “choose another topic”.
  • Full → SessionExpired if the session TTL has elapsed and the session no longer exists.

7.2 Streaming

Meaning

  • Client receives incremental updates via analysisChunk events and renders them as they arrive.

Stream semantics

  • A sequence of analysisChunk events arrives in order.
  • For a given streaming request, no further analysisChunk events are sent once one of the following occurs:
    • execution completes and the backend emits analysisStatus(status="completed")
    • a paywall is emitted (visibility is gated)
    • an error is emitted (see stream_protocol.md).

Exit

  • Streaming → Full when execution completes and the client transitions to a stable “completed” view.
  • Streaming → Preview when a terminal paywall is received.
  • Streaming → SessionExpired if the session TTL has elapsed and the next operation fails.

8. Session Expiry: SessionExpired

8.1 Session lifetime

Contract-level semantics

  • Sessions have a finite TTL (implementation-defined).
  • After TTL, REST inspection may return “not found or expired”, and streaming may return a terminal error.

8.2 Client behavior

Meaning

  • SessionExpired represents any state where the client holds a sessionId, but the backend no longer recognizes it.

Reachability

  • TopicSelection → SessionExpired
  • Preview → SessionExpired
  • Full → SessionExpired

Typical UX

  • Show an “expired session” message and guide the user back to the input surface to create a new session.

9. Error Handling (Out-of-band)

The diagram omits generic error paths for clarity. In the MVP:

  • Any stream error event moves the result surface into an error view.
  • Any REST error on session creation or checkout keeps the client in its current state with inline error UX.

These are implementation details and intentionally not modeled as separate primary states.


10. How to Read This with the Other Contracts

To review the C1 surface end-to-end: