/ rfcs / 0011-phase4-browser-runtime.md
0011-phase4-browser-runtime.md
  1  # RFC-0011 — Phase 4 Browser Runtime
  2  
  3  Status: Accepted
  4  
  5  ## Summary
  6  
  7  Implement a minimal browser runtime in `client/lightspeed.js` with:
  8  
  9  - connect/reconnect loop
 10  - delegated browser events
 11  - patch application
 12  - ack protocol behavior
 13  - loading/error states
 14  - client-side hooks API draft
 15  
 16  ## Motivation
 17  
 18  Phase 3 introduced protocol codec and transport adapters, but no concrete browser runtime consumed that protocol in the DOM. Phase 4 requires a practical client that can mount a live view and maintain reliable patch/event flow.
 19  
 20  ## Design
 21  
 22  ### Runtime API
 23  
 24  Provide:
 25  
 26  - `LightspeedClient`
 27  - `mountLightspeed(options)`
 28  - `encodeFrame(frame)` and `decodeFrame(payload)` helpers
 29  
 30  Runtime resolves root from `[data-ls-root]` or `#app`, and URL from explicit config or `data-ls-ws`.
 31  
 32  ### Protocol behavior
 33  
 34  - send `hello` frame on socket open
 35  - decode incoming frame payloads
 36  - apply `diff` frame HTML patches to root
 37  - send `ack` after successful patch apply
 38  - send `failure` frames on decode/patch errors
 39  
 40  ### Event delegation
 41  
 42  Delegate `click` and `submit` from root to `[data-ls-event]` targets, then send `event` frames with client-generated references.
 43  
 44  ### Reconnect loop
 45  
 46  On non-manual close:
 47  
 48  - transition to `reconnecting`
 49  - schedule exponential backoff reconnect
 50  - reconnect and re-send `hello` on open
 51  
 52  ### Loading/error state model
 53  
 54  Expose runtime state through root dataset markers:
 55  
 56  - `data-ls-client-state`
 57  - `data-ls-loading`
 58  - `data-ls-error`
 59  
 60  Emit custom events:
 61  
 62  - `lightspeed:state`
 63  - `lightspeed:error`
 64  
 65  ### Hooks API draft
 66  
 67  Support `data-ls-hook` elements with optional callbacks:
 68  
 69  - `mounted`
 70  - `updated`
 71  - `destroyed`
 72  - `disconnected`
 73  - `reconnected`
 74  
 75  Hook context includes client handle and `pushEvent`.
 76  
 77  ### Duplicate patch handling
 78  
 79  Duplicate `diff` references are treated idempotently:
 80  
 81  - patch is not re-applied
 82  - `ack` is re-sent deterministically
 83  
 84  ## API impact
 85  
 86  Adds browser runtime module API in `client/lightspeed.js`.
 87  
 88  ## Protocol impact
 89  
 90  Consumes existing frame model and codec; no new frame types.
 91  
 92  ## ISA impact
 93  
 94  No ISA changes.
 95  
 96  ## Security impact
 97  
 98  - runtime does not evaluate arbitrary script content from patches
 99  - failures are surfaced through explicit protocol failure frames
100  - delegated events require explicit `data-ls-event` markers
101  
102  ## Alternatives
103  
104  - implement browser runtime in Gleam-to-JS first
105  - postpone hooks until a later phase
106  - use JSON-only browser codec instead of shared delimited codec
107  
108  ## Unresolved questions
109  
110  - Should reconnect frame include explicit rejoin metadata beyond hello?
111  - Should hook lifecycle include per-event callbacks in Phase 5?