redweb 0.16.2 → 0.16.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/CHANGELOG.md +40 -29
  2. package/README.md +293 -291
  3. package/contract.d.ts +11 -11
  4. package/docs/API_EXAMPLES_VERIFICATION.md +22 -22
  5. package/docs/APPLICATION.md +96 -94
  6. package/docs/CLI.md +122 -122
  7. package/docs/CLIENT_DEVELOPMENT.md +9 -9
  8. package/docs/CONNECTED_CLIENTS_VERIFICATION.md +65 -65
  9. package/docs/DEVELOPMENT.md +81 -81
  10. package/docs/GETTING_STARTED.md +78 -78
  11. package/docs/LIVE_HTML.md +555 -478
  12. package/docs/MIGRATION.md +28 -28
  13. package/docs/RELEASE_TRUST.md +88 -88
  14. package/docs/RUNTIME_DIAGNOSTICS.md +78 -78
  15. package/docs/SOCKET_CONTRACTS.md +42 -42
  16. package/docs/SOCKET_PAGES.md +172 -172
  17. package/docs/SOCKET_PAGE_RELEASE_PREPARATION.md +120 -120
  18. package/docs/SOCKET_PAGE_VERIFICATION.md +85 -85
  19. package/docs/generated.json +2290 -2286
  20. package/docs/guides/chatroom.md +1 -1
  21. package/docs/guides/jsx-without-react.md +14 -14
  22. package/docs/reference.json +1333 -1329
  23. package/docs/releases/0.15.0.json +2217 -2217
  24. package/docs/releases/0.16.0.json +2217 -2217
  25. package/docs/releases/0.16.1.json +2286 -2286
  26. package/docs/releases/0.16.2.json +2286 -2286
  27. package/docs/releases/0.16.3.json +2286 -0
  28. package/docs/releases/0.16.4.json +2290 -0
  29. package/docs/snippets/components.tsx +24 -24
  30. package/docs/snippets/counter.tsx +16 -16
  31. package/docs/snippets/room-access.tsx +11 -11
  32. package/docs/snippets/site.css +2 -2
  33. package/docs/snippets/site.tsx +22 -22
  34. package/docs/topics.json +3 -3
  35. package/index.d.ts +96 -58
  36. package/index.js +14 -8
  37. package/package.json +12 -8
  38. package/recipes/foundation/README.md +7 -7
  39. package/recipes/foundation/app.test.cjs +15 -15
  40. package/recipes/foundation/app.tsx +12 -12
  41. package/recipes/shared/README.md +7 -7
  42. package/src/Application.js +4 -4
  43. package/src/access/failure-codes.json +4 -0
  44. package/src/cli/ProjectInitializer.js +1 -1
  45. package/src/cli/arguments.js +21 -21
  46. package/src/cli/run.js +12 -12
  47. package/src/cli/templates.js +40 -40
  48. package/src/docs/Documentation.js +29 -29
  49. package/src/htmx/CodeHighlight.js +98 -0
  50. package/src/htmx/Html.js +4 -3
  51. package/src/htmx/Jsx.js +2 -2
  52. package/src/htmx/LiveHtmlServer.js +5 -1
  53. package/src/htmx/LivePage.js +5 -1
  54. package/src/htmx/LiveResource.js +96 -0
  55. package/src/htmx/PageManager.js +126 -13
  56. package/src/htmx/PageSocketRoute.js +132 -132
  57. package/src/htmx/PageTaskLane.js +39 -0
  58. package/src/htmx/ReactiveRenderer.js +8 -8
  59. package/src/htmx/SocketAction.js +19 -19
  60. package/src/htmx/TemplateRenderer.js +1 -1
  61. package/src/htmx/index.js +4 -2
  62. package/src/htmx/metadata.js +117 -6
  63. package/src/ws/BaseHandler.js +6 -6
  64. package/src/ws/ConnectedClients.js +207 -207
  65. package/src/ws/HandlerGuard.js +4 -4
  66. package/src/ws/RoomRegistry.js +4 -4
  67. package/src/ws/RouteRuntime.js +11 -11
  68. package/src/ws/SocketAction.js +16 -16
  69. package/src/ws/SocketContract.js +3 -3
  70. package/src/ws/SocketRoute.js +7 -7
  71. package/styles/code-highlight.css +16 -0
@@ -1,16 +1,16 @@
1
1
  # Developing Redweb with redweb-client
2
2
 
3
3
  The Live HTML implementation is maintained in published `redweb-client/live-html`
4
- starting with client 0.2.0. Redweb 0.15.0 requires client `^0.3.0`;
4
+ starting with client 0.2.0. Redweb 0.15.0 requires client `^0.3.0`;
5
5
  normal application installation retrieves it automatically. The linking workflow
6
6
  below is optional for contributors editing both repositories.
7
7
  Redweb serves that module and emits only its import and `mountLivePage()` call.
8
- DOM reconciliation, reactive updates, delegated actions, form feedback and page
9
- disposal belong to the client. The root `redweb-client` entry remains socket-only.
10
-
11
- Socket-bound TSX command bindings and terminal-response filtering use the published
12
- client 0.3.0 runtime. No link is needed for applications using Redweb 0.15.0.
13
- See [socket pages](SOCKET_PAGES.md).
8
+ DOM reconciliation, reactive updates, delegated actions, form feedback and page
9
+ disposal belong to the client. The root `redweb-client` entry remains socket-only.
10
+
11
+ Socket-bound TSX command bindings and terminal-response filtering use the published
12
+ client 0.3.0 runtime. No link is needed for applications using Redweb 0.15.0.
13
+ See [socket pages](SOCKET_PAGES.md).
14
14
 
15
15
  ## Link the sibling repositories
16
16
 
@@ -111,7 +111,7 @@ For example, from Redweb in PowerShell (use a fresh output directory):
111
111
  npm --prefix ../redweb-client run build
112
112
  New-Item -ItemType Directory -Path coverage/client-candidate
113
113
  npm pack ../redweb-client --pack-destination coverage/client-candidate
114
- $env:REDWEB_CLIENT_CANDIDATE = (Resolve-Path coverage/client-candidate/redweb-client-0.3.0.tgz).Path
114
+ $env:REDWEB_CLIENT_CANDIDATE = (Resolve-Path coverage/client-candidate/redweb-client-0.3.0.tgz).Path
115
115
  npm run verify:live-html:package
116
116
  Remove-Item Env:REDWEB_CLIENT_CANDIDATE
117
117
  ```
@@ -147,7 +147,7 @@ bundles with the source-tested local build and run the same browser checks.
147
147
  A candidate pass is not a registry release pass. `npm run verify:package:tools` includes the fingerprint/containment
148
148
  unit regressions; its scoped coverage is not coverage of every browser driver.
149
149
 
150
- Historically, published `redweb-client@0.2.0` supplied both required entry points; version 0.1.0
150
+ Historically, published `redweb-client@0.2.0` supplied both required entry points; version 0.1.0
151
151
  does not. The 0.2.0 archive's runtime bundles match the previously source-tested
152
152
  build, and the clean registry-installed package gate passes without an override.
153
153
  The developer link can remain in place because registry checks own independent
@@ -1,65 +1,65 @@
1
- # Connected-client implementation verification
2
-
3
- Date: 2026-09-02. Runtime commit: `e001a58`, branch `codex/connected-clients`.
4
- This is an unreleased development feature, not the published Redweb 0.15.0 package.
5
- No client source changes or client publication are required; tests use published
6
- redweb-client 0.3.0.
7
-
8
- ## Scope
9
-
10
- `connectedClients` composes the existing RoomRegistry, bounded authorization,
11
- projection work, typed socket handlers and private page ownership. It introduces
12
- no second membership registry. The tutorial consumes it on the companion site's
13
- `codex/tutorial-connected-clients` branch.
14
-
15
- ## Passed gates
16
-
17
- - `npm run pretest`: generated examples, protocol types, development documentation
18
- and all three TypeScript consumer configurations.
19
- - 368 unit/integration tests in 25 suites: socket servers/routes, connected clients,
20
- room access, multiplayer policies/state, protocol/contracts, socket pages,
21
- distribution, inspection, page access and the existing HTML test directory.
22
- - Coverage: 100% statements, branches, functions and lines in **ConnectedClients.js,
23
- RoomRegistry.js, RouteRuntime.js and SocketRoute.js**. Report:
24
- `coverage/connected-client-rooms`. This is an affected-module claim, not a claim
25
- that every module in the repository was measured by this command.
26
- - `npm run verify:live-html:package`: actual tarball installed in isolation;
27
- counter, chat, reconnect/disconnect, cards, components, JSX, dashboard login,
28
- generated starters, rendering and development-refresh browser checks passed.
29
- Browser: headed Google Chrome 152.0.7977.64. Existing bundled HTML-runtime and
30
- refresh coverage gates also reached 100% in their declared scopes.
31
- - Production dependency audit: zero reported vulnerabilities.
32
-
33
- Packed runtime SHA-256 (before adding this evidence document):
34
- `818bfeb32683089b883bd88f2cef8ac444a8611365a9fe121b4fe2d6b597e540`.
35
- Package verification report:
36
- `coverage/packed-browser/8a79c650-cf59-460b-b024-ad791406147f`.
37
- The archive retains the development checkout's 0.15.0 manifest version; it is
38
- **not** the npm release bearing that version and must not be published over it.
39
-
40
- ## Real-network regressions
41
-
42
- Independent tabs receive separate private pages; presence counts unique identities
43
- and reacts to the last tab disconnecting. Tests also cover capacity before domain
44
- commit, rejected-join membership rollback, room isolation, authorization revoked
45
- during validation/projection, stale successful and failed projections, failing
46
- recipients, page-only groups, raw clients and overlapping commands.
47
-
48
- Senior critic findings were fixed and regression-tested:
49
-
50
- 1. A stale authorization/projection failure cannot disconnect a newer valid view.
51
- 2. Raw command completion is independent of superseded state projections.
52
- 3. Raw rejection adapters are bounded and cancel when the connection closes.
53
-
54
- No soak or long fixed-observation-time tests were run. Test timeouts are failure
55
- deadlines. Application callbacks still must validate before mutating domain state;
56
- membership rollback is not an arbitrary application/database transaction.
57
-
58
- ## Release boundary
59
-
60
- The implementation above was tested as unreleased. Release preparation now targets
61
- **0.16.0**, with matching package/lock metadata and a generated immutable release
62
- catalogue. This preparation does not publish the package or change runtime code.
63
- After publication, update the site's dependency pins, lockfiles and catalogue;
64
- remove development-preview notices and retest the archive against registry packages
65
- before manual deployment. Immutable published documentation snapshots are unchanged.
1
+ # Connected-client implementation verification
2
+
3
+ Date: 2026-09-02. Runtime commit: `e001a58`, branch `codex/connected-clients`.
4
+ This is an unreleased development feature, not the published Redweb 0.15.0 package.
5
+ No client source changes or client publication are required; tests use published
6
+ redweb-client 0.3.0.
7
+
8
+ ## Scope
9
+
10
+ `connectedClients` composes the existing RoomRegistry, bounded authorization,
11
+ projection work, typed socket handlers and private page ownership. It introduces
12
+ no second membership registry. The tutorial consumes it on the companion site's
13
+ `codex/tutorial-connected-clients` branch.
14
+
15
+ ## Passed gates
16
+
17
+ - `npm run pretest`: generated examples, protocol types, development documentation
18
+ and all three TypeScript consumer configurations.
19
+ - 368 unit/integration tests in 25 suites: socket servers/routes, connected clients,
20
+ room access, multiplayer policies/state, protocol/contracts, socket pages,
21
+ distribution, inspection, page access and the existing HTML test directory.
22
+ - Coverage: 100% statements, branches, functions and lines in **ConnectedClients.js,
23
+ RoomRegistry.js, RouteRuntime.js and SocketRoute.js**. Report:
24
+ `coverage/connected-client-rooms`. This is an affected-module claim, not a claim
25
+ that every module in the repository was measured by this command.
26
+ - `npm run verify:live-html:package`: actual tarball installed in isolation;
27
+ counter, chat, reconnect/disconnect, cards, components, JSX, dashboard login,
28
+ generated starters, rendering and development-refresh browser checks passed.
29
+ Browser: headed Google Chrome 152.0.7977.64. Existing bundled HTML-runtime and
30
+ refresh coverage gates also reached 100% in their declared scopes.
31
+ - Production dependency audit: zero reported vulnerabilities.
32
+
33
+ Packed runtime SHA-256 (before adding this evidence document):
34
+ `818bfeb32683089b883bd88f2cef8ac444a8611365a9fe121b4fe2d6b597e540`.
35
+ Package verification report:
36
+ `coverage/packed-browser/8a79c650-cf59-460b-b024-ad791406147f`.
37
+ The archive retains the development checkout's 0.15.0 manifest version; it is
38
+ **not** the npm release bearing that version and must not be published over it.
39
+
40
+ ## Real-network regressions
41
+
42
+ Independent tabs receive separate private pages; presence counts unique identities
43
+ and reacts to the last tab disconnecting. Tests also cover capacity before domain
44
+ commit, rejected-join membership rollback, room isolation, authorization revoked
45
+ during validation/projection, stale successful and failed projections, failing
46
+ recipients, page-only groups, raw clients and overlapping commands.
47
+
48
+ Senior critic findings were fixed and regression-tested:
49
+
50
+ 1. A stale authorization/projection failure cannot disconnect a newer valid view.
51
+ 2. Raw command completion is independent of superseded state projections.
52
+ 3. Raw rejection adapters are bounded and cancel when the connection closes.
53
+
54
+ No soak or long fixed-observation-time tests were run. Test timeouts are failure
55
+ deadlines. Application callbacks still must validate before mutating domain state;
56
+ membership rollback is not an arbitrary application/database transaction.
57
+
58
+ ## Release boundary
59
+
60
+ The implementation above was tested as unreleased. Release preparation now targets
61
+ **0.16.0**, with matching package/lock metadata and a generated immutable release
62
+ catalogue. This preparation does not publish the package or change runtime code.
63
+ After publication, update the site's dependency pins, lockfiles and catalogue;
64
+ remove development-preview notices and retest the archive against registry packages
65
+ before manual deployment. Immutable published documentation snapshots are unchanged.
@@ -1,81 +1,81 @@
1
- # Development refresh and inspection
2
-
3
- This API is available in `redweb@0.16.2`. Use documentation matching the installed package before enabling it.
4
-
5
- ## Browser refresh
6
-
7
- The generated `npm run dev` command enables browser refresh while rebuilding and restarting your application. No extra application code is needed. For an existing Live HTML application, enable it explicitly:
8
-
9
- ```ts
10
- const app = defineApp({ pages: [CounterPage], development: { refresh: true } });
11
- app.run();
12
- ```
13
-
14
- Alternatively, set `REDWEB_DEV_REFRESH=1` only for your development process. Explicit `development: { refresh: false }` overrides that environment flag. Setting `NODE_ENV=development` alone enables neither refresh nor inspection. Both features are refused at construction under `NODE_ENV=production`; changing environment variables after construction is not a mode switch. `npm start` does not set the refresh flag. Keep it out of production environments.
15
-
16
- On direct loopback access, the initial HTML embeds the serving process's revision. The browser polls the same listener sequentially, with a two-second request deadline and one second between completed attempts. Only a valid, different revision triggers refresh. Failed builds, unavailable listeners, malformed responses and redirects do not cause reload loops. A restart before the external script finishes loading is still detected against the revision embedded in the original document.
17
-
18
- Clean pages reload automatically after a new revision appears. The edit guard conservatively keeps the current document if it observes input/change events, sees differing form defaults when it starts, encounters an editable element with focus, or finds contenteditable content. A native, keyboard-operable notice offers **Reload and discard drafts**. Ordinary untouched selects are compared against the browser's actual reset defaults, not simply their `selected` attributes. Once confirmation is required, resetting or submitting a form does not silently permit automatic reload.
19
-
20
- This is not autosave or a precise unsaved-change detector. False positives are intentional; custom editors or programmatic changes without input/change events may not be detected. The helper does not persist or transmit form contents, write browser storage, replay actions, or restore files/passwords after reload. It keeps the current DOM while waiting for your decision. Manual navigation, browser termination, and confirmed reload can discard drafts.
21
-
22
- The notice uses a shadow root so ordinary reactive root updates preserve it and the application controls' existing focus/draft behavior. Its script, stylesheet and revision fetch are same-origin external resources; your CSP must allow those resources. Navigation away stops polling. History restoration resumes it, including back-forward-cache restoration where the browser supports and chooses it.
23
-
24
- ### Connections and server state
25
-
26
- Keeping the old document does **not** make its old page token/session valid on a replacement process. Existing reconnect rules still apply to a temporary connection outage on the same server. A process restart resets in-memory page/chat/counter state; persistent application data remains the application's responsibility. Actions in flight may have uncertain outcomes. Refresh does not retry them, guarantee completion or migrate state. Reload creates a new page session.
27
-
28
- ### Access and resource boundaries
29
-
30
- Refresh is for direct `localhost`, literal `127.x.x.x`, or `[::1]` URLs at the listener's actual port. It verifies the actual loopback peer, Host, any supplied Origin, and Fetch Metadata. It does not trust forwarding headers or support custom hostnames, tunnels or reverse-proxy origins. Rejected requests receive no refresh bootstrap; this restriction does not make the rest of your application private. An application can still bind publicly unless you separately set `bind`.
31
-
32
- Enabled refresh reserves `/__redweb/development`, `/__redweb/development.js` and `/__redweb/development.css`. They reveal only a boot revision, fixed client code and styling—not inspection snapshots, application state or compiler output. Responses and decorated HTML are no-store. There is no extra listener or server timer. Served `live: false` pages support refresh without a live socket client; `exportStatic()` output remains script-free and never enables it from the environment. Raw `SocketServer`/`SecureSocketServer` do not accept the HTML `refresh` option.
33
-
34
- The injected `rw-dev-refresh` element and `__redweb_dev` ID belong to this helper; do not reuse them in application markup. The repository's `npm run verify:development:browser` gate runs actual generated watchers and Chromium against real HTTP/WebSocket listeners, including edited-document confirmation and failed-build recovery. CI runs it separately from the production browser regression gate.
35
-
36
- ## Inspection
37
-
38
- Enable inspection explicitly when starting a development application:
39
-
40
- ```ts
41
- const app = defineApp({
42
- pages: [CounterPage],
43
- development: { inspect: true },
44
- });
45
-
46
- // Await startup before reading live metadata (ESM entry point).
47
- await app.run();
48
- console.dir(app.inspect(), { depth: null });
49
- ```
50
-
51
- `SocketServer` and `SecureSocketServer` accept the same option and expose the same `inspect()` method. Without the option, `inspect()` returns `null`. Merely setting `NODE_ENV=development` does not enable inspection. Explicitly enabling it while `NODE_ENV=production` throws before routes or listeners are attached. The environment check occurs at construction; changing environment variables afterward is not a runtime mode switch.
52
-
53
- Inspection itself is an in-process, read-only API. It does not create an HTTP/debugging route, listener, browser script, background timer, or automatic logger; browser refresh is a separate option and never exposes inspection data. Do not expose inspection results through an application endpoint in production. Your existing `redweb doctor --json` command remains the source/configuration checker; it does not inspect a running process.
54
-
55
- ## What the snapshot means
56
-
57
- `inspect()` returns immutable, versioned JSON-compatible data:
58
-
59
- - `pages.registrations`: configured route paths, live/shared flags, class names, decorated action/state names, and descriptions of currently available owned components. It never constructs a page to discover its members. Standard decorator metadata and component fields may not exist before first construction, so `instanceMetadata: "unobserved"` means an incomplete inventory, not “this page has no actions.” Static or expired pages can have no current instance even when class metadata was observed previously.
60
- - `pages.connections`: separate counts for pending HTTP-created sessions, connected sockets, closing transports or disconnect hooks in progress (`detaching`), and disconnected sessions retained for reconnect. An attached socket that is no longer open is not yet a retained/reconnectable session. Shared pages appear once in each registration's instance list even when several visitors use them.
61
- - `pages.sessions`: bounded per-render descriptions using inspector-local numeric IDs. These are not page tokens, credentials, principal IDs or socket IDs. A reconnect to the same retained page session keeps its renderer ID.
62
- - `sockets.routes`: registered socket paths and handler names, registered connection counts, draining status, and room/session counts. Runtime-added routes and handlers appear on the next read. `pendingUpgrades` counts currently tracked handshakes. Room names, session identifiers and stored data are omitted. A registered raw connection is not a promise that every transport is currently open; lifecycle cleanup may be in progress.
63
- - `history`: the latest reactive state invalidations and flush attempts. A state invalidation lists the member/component name and affected render-owner IDs. An empty affected-owner list means no current reactive owner read that member. Several invalidations can be batched into one flush.
64
-
65
- Page-session and underlying socket counts describe overlapping resources—do not add them together as independent visitors. Counts remain available independently of truncated detail lists. A description failure yields `available: false` for its section without reflecting exception text.
66
-
67
- ## Render history is not delivery tracing
68
-
69
- `flush-started` reports whether the attempt is a reconnect/attach snapshot and which owners were dirty. `flush-completed`, `flush-superseded`, and `flush-failed` describe that attempt, with elapsed milliseconds. Completion can mean unchanged HTML, no transport write, or a transport write that the peer did not receive. It is **not** a delivery acknowledgement. Supersession means a disconnect, disposal or generation change made the attempt obsolete.
70
-
71
- History does not attribute an invalidation to a particular action: timers, services and application code can also assign state. It does not retain action arguments, state values, HTML, request headers, cookies, query parameters, identities, socket contexts, or exception messages. It does not serialize getters or call action/render/lifecycle callbacks to produce a snapshot. Application accessors replacing declaration fields are skipped; standard action metadata excludes replaced accessor methods. This is not a security sandbox against hostile JavaScript Proxies or global monkey-patching.
72
-
73
- The history observes the reactive TSX renderer's connected update path, starting with socket attachment. Initial HTTP rendering, static output, changes with no connected reactive renderer, and nonreactive template `redweb:state` transport messages are not traced. `pages.sessions[].reactive` distinguishes those sessions. Existing runtime failure diagnostics and application tests remain necessary.
74
-
75
- ## Bounds and overhead
76
-
77
- History retains at most 256 entries per inspected server and only primitive metadata; each event's owner list retains at most 100 names. Current page/socket description lists retain at most 100 items each and share a separate 1,000-item budget per snapshot. Lists include `total` and `truncated`. Labels are limited to 128 UTF-16 code units. Names and route paths are application-defined declarations: do not put secrets in them. The local history's `total` is its sequence counter, including any contained recording failure; retained entries may therefore have gaps.
78
-
79
- Inspection selects a specialized renderer once for the enabled server. Ordinary reactive invalidation, flush, and socket-message paths have no inspector callbacks or added inspection branches. Disabled servers retain the original renderer class. The only ordinary rendering seam is renderer-class selection when a page session is constructed. Enabled inspection deliberately does extra metadata work and allocations; its timings are diagnostic observations, not production benchmarks.
80
-
81
- Shutdown removes page sessions and connections through the existing lifecycle. The bounded primitive history remains readable while you retain the server object; it does not keep disposed page instances alive. The inspector's local ID table uses weak keys.
1
+ # Development refresh and inspection
2
+
3
+ This API is available in `redweb@0.16.4`. Use documentation matching the installed package before enabling it.
4
+
5
+ ## Browser refresh
6
+
7
+ The generated `npm run dev` command enables browser refresh while rebuilding and restarting your application. No extra application code is needed. For an existing Live HTML application, enable it explicitly:
8
+
9
+ ```ts
10
+ const app = defineApp({ pages: [CounterPage], development: { refresh: true } });
11
+ app.run();
12
+ ```
13
+
14
+ Alternatively, set `REDWEB_DEV_REFRESH=1` only for your development process. Explicit `development: { refresh: false }` overrides that environment flag. Setting `NODE_ENV=development` alone enables neither refresh nor inspection. Both features are refused at construction under `NODE_ENV=production`; changing environment variables after construction is not a mode switch. `npm start` does not set the refresh flag. Keep it out of production environments.
15
+
16
+ On direct loopback access, the initial HTML embeds the serving process's revision. The browser polls the same listener sequentially, with a two-second request deadline and one second between completed attempts. Only a valid, different revision triggers refresh. Failed builds, unavailable listeners, malformed responses and redirects do not cause reload loops. A restart before the external script finishes loading is still detected against the revision embedded in the original document.
17
+
18
+ Clean pages reload automatically after a new revision appears. The edit guard conservatively keeps the current document if it observes input/change events, sees differing form defaults when it starts, encounters an editable element with focus, or finds contenteditable content. A native, keyboard-operable notice offers **Reload and discard drafts**. Ordinary untouched selects are compared against the browser's actual reset defaults, not simply their `selected` attributes. Once confirmation is required, resetting or submitting a form does not silently permit automatic reload.
19
+
20
+ This is not autosave or a precise unsaved-change detector. False positives are intentional; custom editors or programmatic changes without input/change events may not be detected. The helper does not persist or transmit form contents, write browser storage, replay actions, or restore files/passwords after reload. It keeps the current DOM while waiting for your decision. Manual navigation, browser termination, and confirmed reload can discard drafts.
21
+
22
+ The notice uses a shadow root so ordinary reactive root updates preserve it and the application controls' existing focus/draft behavior. Its script, stylesheet and revision fetch are same-origin external resources; your CSP must allow those resources. Navigation away stops polling. History restoration resumes it, including back-forward-cache restoration where the browser supports and chooses it.
23
+
24
+ ### Connections and server state
25
+
26
+ Keeping the old document does **not** make its old page token/session valid on a replacement process. Existing reconnect rules still apply to a temporary connection outage on the same server. A process restart resets in-memory page/chat/counter state; persistent application data remains the application's responsibility. Actions in flight may have uncertain outcomes. Refresh does not retry them, guarantee completion or migrate state. Reload creates a new page session.
27
+
28
+ ### Access and resource boundaries
29
+
30
+ Refresh is for direct `localhost`, literal `127.x.x.x`, or `[::1]` URLs at the listener's actual port. It verifies the actual loopback peer, Host, any supplied Origin, and Fetch Metadata. It does not trust forwarding headers or support custom hostnames, tunnels or reverse-proxy origins. Rejected requests receive no refresh bootstrap; this restriction does not make the rest of your application private. An application can still bind publicly unless you separately set `bind`.
31
+
32
+ Enabled refresh reserves `/__redweb/development`, `/__redweb/development.js` and `/__redweb/development.css`. They reveal only a boot revision, fixed client code and styling—not inspection snapshots, application state or compiler output. Responses and decorated HTML are no-store. There is no extra listener or server timer. Served `live: false` pages support refresh without a live socket client; `exportStatic()` output remains script-free and never enables it from the environment. Raw `SocketServer`/`SecureSocketServer` do not accept the HTML `refresh` option.
33
+
34
+ The injected `rw-dev-refresh` element and `__redweb_dev` ID belong to this helper; do not reuse them in application markup. The repository's `npm run verify:development:browser` gate runs actual generated watchers and Chromium against real HTTP/WebSocket listeners, including edited-document confirmation and failed-build recovery. CI runs it separately from the production browser regression gate.
35
+
36
+ ## Inspection
37
+
38
+ Enable inspection explicitly when starting a development application:
39
+
40
+ ```ts
41
+ const app = defineApp({
42
+ pages: [CounterPage],
43
+ development: { inspect: true },
44
+ });
45
+
46
+ // Await startup before reading live metadata (ESM entry point).
47
+ await app.run();
48
+ console.dir(app.inspect(), { depth: null });
49
+ ```
50
+
51
+ `SocketServer` and `SecureSocketServer` accept the same option and expose the same `inspect()` method. Without the option, `inspect()` returns `null`. Merely setting `NODE_ENV=development` does not enable inspection. Explicitly enabling it while `NODE_ENV=production` throws before routes or listeners are attached. The environment check occurs at construction; changing environment variables afterward is not a runtime mode switch.
52
+
53
+ Inspection itself is an in-process, read-only API. It does not create an HTTP/debugging route, listener, browser script, background timer, or automatic logger; browser refresh is a separate option and never exposes inspection data. Do not expose inspection results through an application endpoint in production. Your existing `redweb doctor --json` command remains the source/configuration checker; it does not inspect a running process.
54
+
55
+ ## What the snapshot means
56
+
57
+ `inspect()` returns immutable, versioned JSON-compatible data:
58
+
59
+ - `pages.registrations`: configured route paths, live/shared flags, class names, decorated action/state names, and descriptions of currently available owned components. It never constructs a page to discover its members. Standard decorator metadata and component fields may not exist before first construction, so `instanceMetadata: "unobserved"` means an incomplete inventory, not “this page has no actions.” Static or expired pages can have no current instance even when class metadata was observed previously.
60
+ - `pages.connections`: separate counts for pending HTTP-created sessions, connected sockets, closing transports or disconnect hooks in progress (`detaching`), and disconnected sessions retained for reconnect. An attached socket that is no longer open is not yet a retained/reconnectable session. Shared pages appear once in each registration's instance list even when several visitors use them.
61
+ - `pages.sessions`: bounded per-render descriptions using inspector-local numeric IDs. These are not page tokens, credentials, principal IDs or socket IDs. A reconnect to the same retained page session keeps its renderer ID.
62
+ - `sockets.routes`: registered socket paths and handler names, registered connection counts, draining status, and room/session counts. Runtime-added routes and handlers appear on the next read. `pendingUpgrades` counts currently tracked handshakes. Room names, session identifiers and stored data are omitted. A registered raw connection is not a promise that every transport is currently open; lifecycle cleanup may be in progress.
63
+ - `history`: the latest reactive state invalidations and flush attempts. A state invalidation lists the member/component name and affected render-owner IDs. An empty affected-owner list means no current reactive owner read that member. Several invalidations can be batched into one flush.
64
+
65
+ Page-session and underlying socket counts describe overlapping resources—do not add them together as independent visitors. Counts remain available independently of truncated detail lists. A description failure yields `available: false` for its section without reflecting exception text.
66
+
67
+ ## Render history is not delivery tracing
68
+
69
+ `flush-started` reports whether the attempt is a reconnect/attach snapshot and which owners were dirty. `flush-completed`, `flush-superseded`, and `flush-failed` describe that attempt, with elapsed milliseconds. Completion can mean unchanged HTML, no transport write, or a transport write that the peer did not receive. It is **not** a delivery acknowledgement. Supersession means a disconnect, disposal or generation change made the attempt obsolete.
70
+
71
+ History does not attribute an invalidation to a particular action: timers, services and application code can also assign state. It does not retain action arguments, state values, HTML, request headers, cookies, query parameters, identities, socket contexts, or exception messages. It does not serialize getters or call action/render/lifecycle callbacks to produce a snapshot. Application accessors replacing declaration fields are skipped; standard action metadata excludes replaced accessor methods. This is not a security sandbox against hostile JavaScript Proxies or global monkey-patching.
72
+
73
+ The history observes the reactive TSX renderer's connected update path, starting with socket attachment. Initial HTTP rendering, static output, changes with no connected reactive renderer, and nonreactive template `redweb:state` transport messages are not traced. `pages.sessions[].reactive` distinguishes those sessions. Existing runtime failure diagnostics and application tests remain necessary.
74
+
75
+ ## Bounds and overhead
76
+
77
+ History retains at most 256 entries per inspected server and only primitive metadata; each event's owner list retains at most 100 names. Current page/socket description lists retain at most 100 items each and share a separate 1,000-item budget per snapshot. Lists include `total` and `truncated`. Labels are limited to 128 UTF-16 code units. Names and route paths are application-defined declarations: do not put secrets in them. The local history's `total` is its sequence counter, including any contained recording failure; retained entries may therefore have gaps.
78
+
79
+ Inspection selects a specialized renderer once for the enabled server. Ordinary reactive invalidation, flush, and socket-message paths have no inspector callbacks or added inspection branches. Disabled servers retain the original renderer class. The only ordinary rendering seam is renderer-class selection when a page session is constructed. Enabled inspection deliberately does extra metadata work and allocations; its timings are diagnostic observations, not production benchmarks.
80
+
81
+ Shutdown removes page sessions and connections through the existing lifecycle. The bounded primitive history remains readable while you retain the server object; it does not keep disposed page instances alive. The inspector's local ID table uses weak keys.
@@ -1,78 +1,78 @@
1
- # Build a site and its realtime backend together
2
-
3
- Redweb renders TypeScript/TSX on Node.js and connects server-owned state and actions to the browser through WebSockets. Use it for live dashboards, chat, collaboration, documentation sites, and socket services. You can use HTTP or WebSockets independently.
4
-
5
- It is not React, a browser component framework, a database, an identity provider, or a managed multiplayer platform. Do not use React hooks or import `react/jsx-runtime`. An edge-only host without Node listeners cannot run a live Redweb server; exported static pages need no Node runtime.
6
-
7
- ## Start a project
8
-
9
- Create the same neutral foundation whether you are following a tutorial or starting your own application:
10
-
11
- ```sh
12
- npx --yes redweb@0.16.2 init my-app
13
- cd my-app
14
- npm install --save-exact redweb@0.16.2
15
- npm test
16
- npm run dev
17
- ```
18
-
19
- Add capability dependencies without importing example-domain code:
20
-
21
- ```sh
22
- npx --yes redweb@0.16.2 init my-game --with auth,multiplayer
23
- ```
24
-
25
- The default includes its real tests. `--bare` omits only the test directory, test scripts, and test-only coverage dependency; it retains the runnable application, CSS, compiler configuration, build scripts, and development watcher.
26
-
27
- ## Explore complete recipes
28
-
29
- Choose one of these complete applications:
30
-
31
- - [Realtime counter](../recipes/realtime/README.md): the smallest live website, sharing server-owned state between visitors.
32
- - [Chatroom](../recipes/chat/README.md): reusable stateful components, messages, and live presence.
33
- - [Site](../recipes/site/README.md): non-live pages with a shared layout and stylesheet.
34
- - [Socket service](../recipes/socket/README.md): a typed `/match` route with separate join/move/resume handlers.
35
- - [HTTP and WebSockets](../recipes/http-ws/README.md): one listener, an HTTP health endpoint and a raw `/chat` route with an explicit cleanup owner.
36
- - [Private dashboard](../recipes/dashboard/README.md): persistent SQLite cards, account sessions and private live updates (Node 22.13+).
37
-
38
- Named templates are finished examples rather than the default project structure. Each generated recipe page contains its exact files, commands, limitations, and real HTTP/WebSocket acceptance tests. Follow that recipe's version-specific setup instructions rather than mixing an unreleased example with a published npm version.
39
-
40
- Requirements: Node.js satisfying the package's `engines` field and npm. Use a supported Node.js release in production. TypeScript and the development watcher are installed by the starter. No React, frontend bundler or broker is required. Only the dashboard starter uses a database; its native SQLite requirement is recipe-local.
41
-
42
- The installation floor is not a security-support promise for old Node releases. See [runtime compatibility, release verification and provenance](RELEASE_TRUST.md) before choosing a production version.
43
-
44
- ## One development loop
45
-
46
- After initialization and installation, `npm test` compiles the project, copies assets, and runs the shipped network tests. `npm run dev` watches source/configuration files, rebuilds, and restarts. Served HTML pages on direct localhost access refresh when the replacement server is ready; detected edits instead produce a confirmation notice that keeps the current document until explicit reload. This is not autosave or browser hot-module replacement; in-memory state and old socket sessions reset on restart. See [development refresh and its guarantees](DEVELOPMENT.md#browser-refresh).
47
-
48
- Use `.tsx` for markup and extend `redweb/tsconfig.json`. Colocate CSS with the decorated page/component or declare an explicit asset root. `npm run build` prepares `dist/`; `npm start` runs that compiled application.
49
-
50
- When setup fails, run `npx --no-install redweb doctor --json` from the application directory. Fix reported errors and examine unresolved warnings, then rerun the build and real tests. Doctor does not execute application code or prove application correctness. See [diagnostics and boundaries](CLI.md).
51
-
52
- ## The mental model
53
-
54
- - A page is a decorated class. Its `render()` returns server-side TSX.
55
- - State is server-owned data. An ordinary TSX expression reading `@state()` updates automatically when that property is assigned. Replace arrays/objects rather than mutating them in place.
56
- - Ordinary live pages expose decorated actions. Socket-bound pages expose their registered typed handlers through TSX controls. Validate and authorize every untrusted input; hiding a button is not access control.
57
- - A class component owns reusable state/actions and has its own update boundary. Function components are convenient presentation helpers.
58
- - Pages are connection-scoped by default. `shared: true` intentionally shares one page instance; do not put private visitor data there.
59
- - Shared in-memory state survives visitors and reloads, not server restarts. Durable cards/history require application-owned persistence. Multiple processes do not automatically share memory.
60
- - Socket URLs select routes; message `type` selects a handler. Do not add a second `message.action` dispatcher inside a catch-all handler.
61
-
62
- See [rendering and lifecycle](LIVE_HTML.md) and [shared socket contracts](SOCKET_CONTRACTS.md) for exact semantics.
63
-
64
- For private raw socket subscriptions, see [room authorization and shared request identity](ROOM_AUTHORIZATION.md). Keep authentication, subscription permission, and application-specific write permission explicit.
65
-
66
- ## Deploy deliberately
67
-
68
- Build first. Deploy `dist/`, the package manifest, and the lockfile, then install runtime dependencies with `npm ci --omit=dev`. The starters are tested with `src/` unavailable after compilation. Configure HTTPS/WSS and a proxy that supports WebSocket upgrades when using a reverse proxy.
69
-
70
- These deployment commands require a verified release pair. `redweb@0.16.2` installs published `redweb-client@0.3.0` automatically through its dependency. Future unreleased Redweb changes require their matching tested tarball until a release containing them is published. The `npm link` workflow is local development only: a clean production install does not preserve that link.
71
-
72
- Before public access, add authentication, authorization, trusted-origin policy, input/rate limits, application persistence where needed, and bounded shutdown. Treat reconnect/session tokens as credentials. Do not promise exactly-once delivery or durable sessions from an in-memory starter. See [operations](MULTIPLAYER_OPERATIONS.md) and [guarantees and limits](PRODUCTION_READINESS.md).
73
-
74
- ## Evidence and compatibility
75
-
76
- Complete recipe files are executable applications; shorter API snippets explain individual methods and may require surrounding application code. Type-check and test a complete recipe before adapting it. The package verifier runs the documented recipe files against an extracted tarball and actual listeners, not mocks.
77
-
78
- Coverage reports refer to instrumented library code. They do not prove exhaustive browser behavior, application security, all generated-example branches, or production capacity. Historical [verification evidence](VERIFICATION_EVIDENCE.md) applies only to its recorded revision/environment; consult the [current release checklist](AGENT_READY_ACCEPTANCE.md) for remaining work.
1
+ # Build a site and its realtime backend together
2
+
3
+ Redweb renders TypeScript/TSX on Node.js and connects server-owned state and actions to the browser through WebSockets. Use it for live dashboards, chat, collaboration, documentation sites, and socket services. You can use HTTP or WebSockets independently.
4
+
5
+ It is not React, a browser component framework, a database, an identity provider, or a managed multiplayer platform. Do not use React hooks or import `react/jsx-runtime`. An edge-only host without Node listeners cannot run a live Redweb server; exported static pages need no Node runtime.
6
+
7
+ ## Start a project
8
+
9
+ Create the same neutral foundation whether you are following a tutorial or starting your own application:
10
+
11
+ ```sh
12
+ npx --yes redweb@0.16.4 init my-app
13
+ cd my-app
14
+ npm install --save-exact redweb@0.16.4
15
+ npm test
16
+ npm run dev
17
+ ```
18
+
19
+ Add capability dependencies without importing example-domain code:
20
+
21
+ ```sh
22
+ npx --yes redweb@0.16.4 init my-game --with auth,multiplayer
23
+ ```
24
+
25
+ The default includes its real tests. `--bare` omits only the test directory, test scripts, and test-only coverage dependency; it retains the runnable application, CSS, compiler configuration, build scripts, and development watcher.
26
+
27
+ ## Explore complete recipes
28
+
29
+ Choose one of these complete applications:
30
+
31
+ - [Realtime counter](../recipes/realtime/README.md): the smallest live website, sharing server-owned state between visitors.
32
+ - [Chatroom](../recipes/chat/README.md): reusable stateful components, messages, and live presence.
33
+ - [Site](../recipes/site/README.md): non-live pages with a shared layout and stylesheet.
34
+ - [Socket service](../recipes/socket/README.md): a typed `/match` route with separate join/move/resume handlers.
35
+ - [HTTP and WebSockets](../recipes/http-ws/README.md): one listener, an HTTP health endpoint and a raw `/chat` route with an explicit cleanup owner.
36
+ - [Private dashboard](../recipes/dashboard/README.md): persistent SQLite cards, account sessions and private live updates (Node 22.13+).
37
+
38
+ Named templates are finished examples rather than the default project structure. Each generated recipe page contains its exact files, commands, limitations, and real HTTP/WebSocket acceptance tests. Follow that recipe's version-specific setup instructions rather than mixing an unreleased example with a published npm version.
39
+
40
+ Requirements: Node.js satisfying the package's `engines` field and npm. Use a supported Node.js release in production. TypeScript and the development watcher are installed by the starter. No React, frontend bundler or broker is required. Only the dashboard starter uses a database; its native SQLite requirement is recipe-local.
41
+
42
+ The installation floor is not a security-support promise for old Node releases. See [runtime compatibility, release verification and provenance](RELEASE_TRUST.md) before choosing a production version.
43
+
44
+ ## One development loop
45
+
46
+ After initialization and installation, `npm test` compiles the project, copies assets, and runs the shipped network tests. `npm run dev` watches source/configuration files, rebuilds, and restarts. Served HTML pages on direct localhost access refresh when the replacement server is ready; detected edits instead produce a confirmation notice that keeps the current document until explicit reload. This is not autosave or browser hot-module replacement; in-memory state and old socket sessions reset on restart. See [development refresh and its guarantees](DEVELOPMENT.md#browser-refresh).
47
+
48
+ Use `.tsx` for markup and extend `redweb/tsconfig.json`. Colocate CSS with the decorated page/component or declare an explicit asset root. `npm run build` prepares `dist/`; `npm start` runs that compiled application.
49
+
50
+ When setup fails, run `npx --no-install redweb doctor --json` from the application directory. Fix reported errors and examine unresolved warnings, then rerun the build and real tests. Doctor does not execute application code or prove application correctness. See [diagnostics and boundaries](CLI.md).
51
+
52
+ ## The mental model
53
+
54
+ - A page is a decorated class. Its `render()` returns server-side TSX.
55
+ - State is server-owned data. An ordinary TSX expression reading `@state()` updates automatically when that property is assigned. Replace arrays/objects rather than mutating them in place.
56
+ - Ordinary live pages expose decorated actions. Socket-bound pages expose their registered typed handlers through TSX controls. Validate and authorize every untrusted input; hiding a button is not access control.
57
+ - A class component owns reusable state/actions and has its own update boundary. Function components are convenient presentation helpers.
58
+ - Pages are connection-scoped by default. `shared: true` intentionally shares one page instance; do not put private visitor data there.
59
+ - Shared in-memory state survives visitors and reloads, not server restarts. Durable cards/history require application-owned persistence. Multiple processes do not automatically share memory.
60
+ - Socket URLs select routes; message `type` selects a handler. Do not add a second `message.action` dispatcher inside a catch-all handler.
61
+
62
+ See [rendering and lifecycle](LIVE_HTML.md) and [shared socket contracts](SOCKET_CONTRACTS.md) for exact semantics.
63
+
64
+ For private raw socket subscriptions, see [room authorization and shared request identity](ROOM_AUTHORIZATION.md). Keep authentication, subscription permission, and application-specific write permission explicit.
65
+
66
+ ## Deploy deliberately
67
+
68
+ Build first. Deploy `dist/`, the package manifest, and the lockfile, then install runtime dependencies with `npm ci --omit=dev`. The starters are tested with `src/` unavailable after compilation. Configure HTTPS/WSS and a proxy that supports WebSocket upgrades when using a reverse proxy.
69
+
70
+ These deployment commands require a verified release pair. `redweb@0.16.4` installs published `redweb-client@0.3.1` automatically through its dependency. Future unreleased Redweb changes require their matching tested tarball until a release containing them is published. The `npm link` workflow is local development only: a clean production install does not preserve that link.
71
+
72
+ Before public access, add authentication, authorization, trusted-origin policy, input/rate limits, application persistence where needed, and bounded shutdown. Treat reconnect/session tokens as credentials. Do not promise exactly-once delivery or durable sessions from an in-memory starter. See [operations](MULTIPLAYER_OPERATIONS.md) and [guarantees and limits](PRODUCTION_READINESS.md).
73
+
74
+ ## Evidence and compatibility
75
+
76
+ Complete recipe files are executable applications; shorter API snippets explain individual methods and may require surrounding application code. Type-check and test a complete recipe before adapting it. The package verifier runs the documented recipe files against an extracted tarball and actual listeners, not mocks.
77
+
78
+ Coverage reports refer to instrumented library code. They do not prove exhaustive browser behavior, application security, all generated-example branches, or production capacity. Historical [verification evidence](VERIFICATION_EVIDENCE.md) applies only to its recorded revision/environment; consult the [current release checklist](AGENT_READY_ACCEPTANCE.md) for remaining work.