redweb 0.16.1 → 0.16.3
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.
- package/CHANGELOG.md +35 -22
- package/README.md +293 -289
- package/contract.d.ts +11 -11
- package/docs/API_EXAMPLES_VERIFICATION.md +22 -22
- package/docs/APPLICATION.md +96 -94
- package/docs/CLI.md +122 -116
- package/docs/CLIENT_DEVELOPMENT.md +9 -9
- package/docs/CONNECTED_CLIENTS_VERIFICATION.md +65 -65
- package/docs/DEVELOPMENT.md +81 -81
- package/docs/GETTING_STARTED.md +78 -58
- package/docs/LIVE_HTML.md +555 -478
- package/docs/MIGRATION.md +28 -28
- package/docs/RELEASE_TRUST.md +88 -88
- package/docs/RUNTIME_DIAGNOSTICS.md +78 -78
- package/docs/SOCKET_CONTRACTS.md +42 -42
- package/docs/SOCKET_PAGES.md +172 -172
- package/docs/SOCKET_PAGE_RELEASE_PREPARATION.md +120 -120
- package/docs/SOCKET_PAGE_VERIFICATION.md +85 -85
- package/docs/generated.json +2286 -2286
- package/docs/guides/chatroom.md +1 -1
- package/docs/guides/jsx-without-react.md +14 -14
- package/docs/reference.json +1329 -1329
- package/docs/releases/0.15.0.json +2217 -2217
- package/docs/releases/0.16.0.json +2217 -2217
- package/docs/releases/0.16.1.json +2286 -2286
- package/docs/releases/0.16.2.json +2286 -0
- package/docs/releases/0.16.3.json +2286 -0
- package/docs/snippets/components.tsx +24 -24
- package/docs/snippets/counter.tsx +16 -16
- package/docs/snippets/room-access.tsx +11 -11
- package/docs/snippets/site.css +2 -2
- package/docs/snippets/site.tsx +22 -22
- package/docs/topics.json +3 -3
- package/index.d.ts +92 -57
- package/index.js +13 -8
- package/package.json +8 -8
- package/recipes/foundation/README.md +7 -0
- package/recipes/foundation/app.test.cjs +15 -0
- package/recipes/foundation/app.tsx +12 -0
- package/recipes/shared/README.md +7 -7
- package/src/Application.js +4 -4
- package/src/access/failure-codes.json +4 -0
- package/src/cli/ProjectInitializer.js +1 -1
- package/src/cli/arguments.js +15 -3
- package/src/cli/run.js +10 -1
- package/src/cli/templates.js +34 -21
- package/src/docs/Documentation.js +25 -15
- package/src/htmx/Jsx.js +2 -2
- package/src/htmx/LiveHtmlServer.js +5 -1
- package/src/htmx/LivePage.js +5 -1
- package/src/htmx/LiveResource.js +96 -0
- package/src/htmx/PageManager.js +126 -13
- package/src/htmx/PageSocketRoute.js +132 -132
- package/src/htmx/PageTaskLane.js +39 -0
- package/src/htmx/ReactiveRenderer.js +8 -8
- package/src/htmx/SocketAction.js +19 -19
- package/src/htmx/TemplateRenderer.js +1 -1
- package/src/htmx/index.js +3 -2
- package/src/htmx/metadata.js +117 -6
- package/src/ws/BaseHandler.js +6 -6
- package/src/ws/ConnectedClients.js +207 -207
- package/src/ws/HandlerGuard.js +4 -4
- package/src/ws/RoomRegistry.js +4 -4
- package/src/ws/RouteRuntime.js +11 -11
- package/src/ws/SocketAction.js +16 -16
- package/src/ws/SocketContract.js +3 -3
- package/src/ws/SocketRoute.js +7 -7
package/docs/SOCKET_PAGES.md
CHANGED
|
@@ -1,172 +1,172 @@
|
|
|
1
|
-
# Server-side TSX for custom socket routes
|
|
2
|
-
|
|
3
|
-
## Connected clients (0.16.0)
|
|
4
|
-
|
|
5
|
-
The following convenience layer requires Redweb **0.16.0**; it is not in Redweb 0.15.0.
|
|
6
|
-
It uses existing redweb-client 0.3.0 without a client upgrade.
|
|
7
|
-
|
|
8
|
-
`connectedClients({ identity, page, project })` creates one route-owned group.
|
|
9
|
-
Register it as `connections` in `SocketRoute`; rooms and handler drain tracking
|
|
10
|
-
are enabled by default. Create a fresh group inside each application factory.
|
|
11
|
-
It reuses RoomRegistry capacity, authorization and disconnect cleanup, not a second
|
|
12
|
-
membership map. Normal raw SocketRoute/SocketContract APIs remain unchanged.
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
const players = connectedClients({
|
|
16
|
-
identity: context => account(context.request),
|
|
17
|
-
page: () => GamePage,
|
|
18
|
-
project: (player, room, online) => ({
|
|
19
|
-
game: games.resume(room, player.identity).snapshot(player.identity),
|
|
20
|
-
online,
|
|
21
|
-
}),
|
|
22
|
-
});
|
|
23
|
-
const match = players.bind(contract);
|
|
24
|
-
const Join = match.handler('join', (player, { room }) =>
|
|
25
|
-
player.join(room, () => games.join(room, player.identity)));
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
This is a composition excerpt: the application supplies `account`, `games`, the
|
|
29
|
-
typed `contract`, and decorated `GamePage` state fields. Register the resulting
|
|
30
|
-
handler, contract protocol and `connections: players` on the page's SocketRoute.
|
|
31
|
-
Handler `.with(payload)` bindings keep their inferred input type.
|
|
32
|
-
|
|
33
|
-
The client exposes `identity`, `page`, `rooms`, `room` (exactly one membership),
|
|
34
|
-
`join(room, commit?)`, `leave(room)` and an explicit underlying `socket` escape hatch.
|
|
35
|
-
`players.get(socket)` supports page lifecycle callbacks, and
|
|
36
|
-
`players.refresh(room)` publishes changes made outside a handler. Successful
|
|
37
|
-
handlers automatically refresh their client's current rooms. Room changes batch
|
|
38
|
-
refresh requests; multiple tabs count as one online identity, but receive separate
|
|
39
|
-
private page projections.
|
|
40
|
-
|
|
41
|
-
Identity must remain exactly equal to the admitted principal. The group checks it
|
|
42
|
-
after payload validation and before/after asynchronous projection work. Existing
|
|
43
|
-
page authorization and generation guards remain in force. Access is not granted
|
|
44
|
-
by a button or a room name. The application still defines room access, game rules,
|
|
45
|
-
seat recovery, revisions and durable storage.
|
|
46
|
-
|
|
47
|
-
`join` checks membership capacity/permission before its synchronous domain commit.
|
|
48
|
-
A rejected commit removes newly added membership, but does not remove pre-existing
|
|
49
|
-
membership. Domain operations must validate before changing their own state:
|
|
50
|
-
Redweb cannot roll back arbitrary application or database side effects. Async
|
|
51
|
-
domain commits are rejected; they must not be used as an external transaction.
|
|
52
|
-
|
|
53
|
-
Projection callbacks return partial page state and must be side-effect-free.
|
|
54
|
-
Authorization and projection work use bounded operations (5000ms defaults;
|
|
55
|
-
`authorizationTimeoutMs` and `projectionTimeoutMs` configure them). Disconnect
|
|
56
|
-
cancels delivery; late results and late failures cannot overwrite or disconnect a
|
|
57
|
-
newer generation. Recipient failures do not reject someone else's committed move.
|
|
58
|
-
Cancellation cannot stop arbitrary work inside user callbacks, only its acceptance.
|
|
59
|
-
|
|
60
|
-
Throw `ClientError` only for deliberately public text, or classify domain errors
|
|
61
|
-
with `reject(error): string | undefined`. Unexpected exceptions retain normal
|
|
62
|
-
private server error handling. Optional `errorState(message)` returns page fields
|
|
63
|
-
such as a notice; the framework owns protocol errors and form completion.
|
|
64
|
-
|
|
65
|
-
An optional `raw.update(state)` adapter returns `{ type, payload }` for non-HTML
|
|
66
|
-
clients. Optional `raw.reject(message)` returns an uncorrelated display event.
|
|
67
|
-
Redweb performs the final authorized send, not the adapter. State events are
|
|
68
|
-
uncorrelated; successful raw requests complete with `redweb:result`, while safe
|
|
69
|
-
rejections use correlated protocol errors. With redweb-client use
|
|
70
|
-
`request(type, payload, { responseType: 'redweb:result' })` and subscribe to state
|
|
71
|
-
separately. This is an opt-in completion contract, not a silent change to existing
|
|
72
|
-
raw handlers. Custom adapters must not send from inside their callbacks.
|
|
73
|
-
|
|
74
|
-
## Socket-bound pages (0.15.0)
|
|
75
|
-
|
|
76
|
-
Added in Redweb 0.15.0 with redweb-client 0.3.0, installed automatically by Redweb.
|
|
77
|
-
Earlier Redweb 0.14.0/client 0.2.0 packages do not provide this extension.
|
|
78
|
-
Contributors editing both packages can use the optional npm-link workflow in the repository's `docs/CLIENT_DEVELOPMENT.md`.
|
|
79
|
-
|
|
80
|
-
A live page can attach to a registered custom `SocketRoute` using
|
|
81
|
-
`@page('/', { socket: MatchRoute })`. There is no new view class, no second renderer,
|
|
82
|
-
and no application-specific browser module. Its connection carries ordinary typed
|
|
83
|
-
commands and reserved `redweb:*` rendering/completion messages.
|
|
84
|
-
|
|
85
|
-
## Typed controls
|
|
86
|
-
|
|
87
|
-
`defineSocketContract(...).handler(type, callback)` still returns a handler class.
|
|
88
|
-
That class can now be used as a JSX binding:
|
|
89
|
-
|
|
90
|
-
```tsx
|
|
91
|
-
<form rw-submit={Join}>
|
|
92
|
-
<input name="room" required />
|
|
93
|
-
<button>Join room</button>
|
|
94
|
-
</form>
|
|
95
|
-
|
|
96
|
-
<button rw-click={Move.with({ cell, revision })}>Move</button>
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
`.with()` snapshots JSON data; it never invokes the handler during rendering.
|
|
100
|
-
TypeScript checks the payload's input type. Incoming wire data is independently
|
|
101
|
-
validated by the contract, including asynchronous schemas. Form fields merge over
|
|
102
|
-
the bound object payload. A click sends its bound payload, or an empty object when
|
|
103
|
-
none was supplied. Bound values are untrusted inputs, not server-held secrets or
|
|
104
|
-
authorization capabilities. Do not embed private data in them.
|
|
105
|
-
|
|
106
|
-
Bindings are server-owned identities, not arbitrary function closures. Rendering
|
|
107
|
-
rejects references to handlers absent from the attached route, even if a different
|
|
108
|
-
handler has the same message name. Existing string `rw-click`/`rw-submit` actions
|
|
109
|
-
remain unchanged on ordinary live pages. Socket-bound pages dispatch only their
|
|
110
|
-
custom route handlers; do not mix local `@action()`/`rw-bind` commands into them.
|
|
111
|
-
|
|
112
|
-
## Server-owned client state
|
|
113
|
-
|
|
114
|
-
On an attached connection, `socket.page(PageClass)` returns that connection's
|
|
115
|
-
concrete page after checking its class, ownership and active lifetime:
|
|
116
|
-
|
|
117
|
-
```ts
|
|
118
|
-
if (socket.page) {
|
|
119
|
-
socket.page(GamePage).game = games.snapshot(room, account);
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
Assigning `@state()` fields uses the existing reactive renderer and keyed TSX.
|
|
124
|
-
Raw connections have no `page` accessor and keep their existing socket protocol.
|
|
125
|
-
Shared domain state belongs in a room/service; each private page receives only its
|
|
126
|
-
authorized perspective. Components remain ordinary page-owned Redweb components.
|
|
127
|
-
|
|
128
|
-
## Configuration and boundaries
|
|
129
|
-
|
|
130
|
-
Register the route once in `defineApp({ pages: [GamePage], sockets: [MatchRoute] })`.
|
|
131
|
-
Socket-bound pages must be live, connection-scoped and render TSX. Their route must
|
|
132
|
-
support protocol version `1` with the default `redwebVersion` query parameter and
|
|
133
|
-
explicitly allow duplicate connections (independent tabs). `redweb:*` handler names
|
|
134
|
-
are reserved. Page-enabled routes use ordered, bounded message dispatch and track
|
|
135
|
-
in-flight work for shutdown. JSON commands are supported; binary input is rejected
|
|
136
|
-
on page-attached connections. Raw route connections retain binary handling.
|
|
137
|
-
|
|
138
|
-
The adapter preserves route admission, origin and placement policies, then checks
|
|
139
|
-
the page token, exact route, page identity and page origin. Use `authenticate` for
|
|
140
|
-
page identity and `authorize` for current permissions/session validity. Authorization
|
|
141
|
-
runs before commands, again after contract validation, and before render publication.
|
|
142
|
-
Revocation and disconnect cancel ownership even when validation is still running.
|
|
143
|
-
The page token is not a substitute for credentials.
|
|
144
|
-
|
|
145
|
-
Initial page attachment completes before custom initialization hooks or commands.
|
|
146
|
-
Do not call page commands from initialization hooks expecting those hooks themselves
|
|
147
|
-
to finish first. Each page owns its connection; the same token cannot attach twice.
|
|
148
|
-
|
|
149
|
-
Reconnect reauthenticates, invokes existing `connected()` hooks, and sends a fresh
|
|
150
|
-
rendering snapshot. Game-seat recovery remains in that server hook. Commands are
|
|
151
|
-
not queued or replayed. Page-session expiration requires a reload; game persistence
|
|
152
|
-
is not provided by page retention.
|
|
153
|
-
|
|
154
|
-
## Completion and client runtime
|
|
155
|
-
|
|
156
|
-
After successful handler dispatch, Redweb sends a correlated `redweb:result`.
|
|
157
|
-
The generated runtime waits specifically for that terminal type or a protocol error,
|
|
158
|
-
not intermediate correlated progress messages. Direct client users can opt into
|
|
159
|
-
the same behavior using `client.request(type, payload, { responseType })`; omitting
|
|
160
|
-
the option preserves the existing any-correlated-response behavior.
|
|
161
|
-
|
|
162
|
-
For an expected application rejection, send a safe correlated error with
|
|
163
|
-
`socket.sendProtocolError('GAME_REJECTED', safeMessage, { requestId })` and return
|
|
164
|
-
`false` from the handler. Only literal `false` declines successful dispatch;
|
|
165
|
-
`undefined` remains success. The browser shows error feedback, preserves the form,
|
|
166
|
-
and keeps its connection usable. Returning `false` without sending a correlated
|
|
167
|
-
reply leaves a requesting client waiting until its deadline. Unexpected exceptions
|
|
168
|
-
retain the existing sanitized handler-failure behavior and close the connection.
|
|
169
|
-
|
|
170
|
-
This browser support lives in redweb-client's existing feedback/transport modules.
|
|
171
|
-
The server still owns validation, authorization, game revisions, room fan-out and
|
|
172
|
-
private rendering. Disabled controls are presentation, never permissions.
|
|
1
|
+
# Server-side TSX for custom socket routes
|
|
2
|
+
|
|
3
|
+
## Connected clients (0.16.0)
|
|
4
|
+
|
|
5
|
+
The following convenience layer requires Redweb **0.16.0**; it is not in Redweb 0.15.0.
|
|
6
|
+
It uses existing redweb-client 0.3.0 without a client upgrade.
|
|
7
|
+
|
|
8
|
+
`connectedClients({ identity, page, project })` creates one route-owned group.
|
|
9
|
+
Register it as `connections` in `SocketRoute`; rooms and handler drain tracking
|
|
10
|
+
are enabled by default. Create a fresh group inside each application factory.
|
|
11
|
+
It reuses RoomRegistry capacity, authorization and disconnect cleanup, not a second
|
|
12
|
+
membership map. Normal raw SocketRoute/SocketContract APIs remain unchanged.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
const players = connectedClients({
|
|
16
|
+
identity: context => account(context.request),
|
|
17
|
+
page: () => GamePage,
|
|
18
|
+
project: (player, room, online) => ({
|
|
19
|
+
game: games.resume(room, player.identity).snapshot(player.identity),
|
|
20
|
+
online,
|
|
21
|
+
}),
|
|
22
|
+
});
|
|
23
|
+
const match = players.bind(contract);
|
|
24
|
+
const Join = match.handler('join', (player, { room }) =>
|
|
25
|
+
player.join(room, () => games.join(room, player.identity)));
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This is a composition excerpt: the application supplies `account`, `games`, the
|
|
29
|
+
typed `contract`, and decorated `GamePage` state fields. Register the resulting
|
|
30
|
+
handler, contract protocol and `connections: players` on the page's SocketRoute.
|
|
31
|
+
Handler `.with(payload)` bindings keep their inferred input type.
|
|
32
|
+
|
|
33
|
+
The client exposes `identity`, `page`, `rooms`, `room` (exactly one membership),
|
|
34
|
+
`join(room, commit?)`, `leave(room)` and an explicit underlying `socket` escape hatch.
|
|
35
|
+
`players.get(socket)` supports page lifecycle callbacks, and
|
|
36
|
+
`players.refresh(room)` publishes changes made outside a handler. Successful
|
|
37
|
+
handlers automatically refresh their client's current rooms. Room changes batch
|
|
38
|
+
refresh requests; multiple tabs count as one online identity, but receive separate
|
|
39
|
+
private page projections.
|
|
40
|
+
|
|
41
|
+
Identity must remain exactly equal to the admitted principal. The group checks it
|
|
42
|
+
after payload validation and before/after asynchronous projection work. Existing
|
|
43
|
+
page authorization and generation guards remain in force. Access is not granted
|
|
44
|
+
by a button or a room name. The application still defines room access, game rules,
|
|
45
|
+
seat recovery, revisions and durable storage.
|
|
46
|
+
|
|
47
|
+
`join` checks membership capacity/permission before its synchronous domain commit.
|
|
48
|
+
A rejected commit removes newly added membership, but does not remove pre-existing
|
|
49
|
+
membership. Domain operations must validate before changing their own state:
|
|
50
|
+
Redweb cannot roll back arbitrary application or database side effects. Async
|
|
51
|
+
domain commits are rejected; they must not be used as an external transaction.
|
|
52
|
+
|
|
53
|
+
Projection callbacks return partial page state and must be side-effect-free.
|
|
54
|
+
Authorization and projection work use bounded operations (5000ms defaults;
|
|
55
|
+
`authorizationTimeoutMs` and `projectionTimeoutMs` configure them). Disconnect
|
|
56
|
+
cancels delivery; late results and late failures cannot overwrite or disconnect a
|
|
57
|
+
newer generation. Recipient failures do not reject someone else's committed move.
|
|
58
|
+
Cancellation cannot stop arbitrary work inside user callbacks, only its acceptance.
|
|
59
|
+
|
|
60
|
+
Throw `ClientError` only for deliberately public text, or classify domain errors
|
|
61
|
+
with `reject(error): string | undefined`. Unexpected exceptions retain normal
|
|
62
|
+
private server error handling. Optional `errorState(message)` returns page fields
|
|
63
|
+
such as a notice; the framework owns protocol errors and form completion.
|
|
64
|
+
|
|
65
|
+
An optional `raw.update(state)` adapter returns `{ type, payload }` for non-HTML
|
|
66
|
+
clients. Optional `raw.reject(message)` returns an uncorrelated display event.
|
|
67
|
+
Redweb performs the final authorized send, not the adapter. State events are
|
|
68
|
+
uncorrelated; successful raw requests complete with `redweb:result`, while safe
|
|
69
|
+
rejections use correlated protocol errors. With redweb-client use
|
|
70
|
+
`request(type, payload, { responseType: 'redweb:result' })` and subscribe to state
|
|
71
|
+
separately. This is an opt-in completion contract, not a silent change to existing
|
|
72
|
+
raw handlers. Custom adapters must not send from inside their callbacks.
|
|
73
|
+
|
|
74
|
+
## Socket-bound pages (0.15.0)
|
|
75
|
+
|
|
76
|
+
Added in Redweb 0.15.0 with redweb-client 0.3.0, installed automatically by Redweb.
|
|
77
|
+
Earlier Redweb 0.14.0/client 0.2.0 packages do not provide this extension.
|
|
78
|
+
Contributors editing both packages can use the optional npm-link workflow in the repository's `docs/CLIENT_DEVELOPMENT.md`.
|
|
79
|
+
|
|
80
|
+
A live page can attach to a registered custom `SocketRoute` using
|
|
81
|
+
`@page('/', { socket: MatchRoute })`. There is no new view class, no second renderer,
|
|
82
|
+
and no application-specific browser module. Its connection carries ordinary typed
|
|
83
|
+
commands and reserved `redweb:*` rendering/completion messages.
|
|
84
|
+
|
|
85
|
+
## Typed controls
|
|
86
|
+
|
|
87
|
+
`defineSocketContract(...).handler(type, callback)` still returns a handler class.
|
|
88
|
+
That class can now be used as a JSX binding:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
<form rw-submit={Join}>
|
|
92
|
+
<input name="room" required />
|
|
93
|
+
<button>Join room</button>
|
|
94
|
+
</form>
|
|
95
|
+
|
|
96
|
+
<button rw-click={Move.with({ cell, revision })}>Move</button>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`.with()` snapshots JSON data; it never invokes the handler during rendering.
|
|
100
|
+
TypeScript checks the payload's input type. Incoming wire data is independently
|
|
101
|
+
validated by the contract, including asynchronous schemas. Form fields merge over
|
|
102
|
+
the bound object payload. A click sends its bound payload, or an empty object when
|
|
103
|
+
none was supplied. Bound values are untrusted inputs, not server-held secrets or
|
|
104
|
+
authorization capabilities. Do not embed private data in them.
|
|
105
|
+
|
|
106
|
+
Bindings are server-owned identities, not arbitrary function closures. Rendering
|
|
107
|
+
rejects references to handlers absent from the attached route, even if a different
|
|
108
|
+
handler has the same message name. Existing string `rw-click`/`rw-submit` actions
|
|
109
|
+
remain unchanged on ordinary live pages. Socket-bound pages dispatch only their
|
|
110
|
+
custom route handlers; do not mix local `@action()`/`rw-bind` commands into them.
|
|
111
|
+
|
|
112
|
+
## Server-owned client state
|
|
113
|
+
|
|
114
|
+
On an attached connection, `socket.page(PageClass)` returns that connection's
|
|
115
|
+
concrete page after checking its class, ownership and active lifetime:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
if (socket.page) {
|
|
119
|
+
socket.page(GamePage).game = games.snapshot(room, account);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Assigning `@state()` fields uses the existing reactive renderer and keyed TSX.
|
|
124
|
+
Raw connections have no `page` accessor and keep their existing socket protocol.
|
|
125
|
+
Shared domain state belongs in a room/service; each private page receives only its
|
|
126
|
+
authorized perspective. Components remain ordinary page-owned Redweb components.
|
|
127
|
+
|
|
128
|
+
## Configuration and boundaries
|
|
129
|
+
|
|
130
|
+
Register the route once in `defineApp({ pages: [GamePage], sockets: [MatchRoute] })`.
|
|
131
|
+
Socket-bound pages must be live, connection-scoped and render TSX. Their route must
|
|
132
|
+
support protocol version `1` with the default `redwebVersion` query parameter and
|
|
133
|
+
explicitly allow duplicate connections (independent tabs). `redweb:*` handler names
|
|
134
|
+
are reserved. Page-enabled routes use ordered, bounded message dispatch and track
|
|
135
|
+
in-flight work for shutdown. JSON commands are supported; binary input is rejected
|
|
136
|
+
on page-attached connections. Raw route connections retain binary handling.
|
|
137
|
+
|
|
138
|
+
The adapter preserves route admission, origin and placement policies, then checks
|
|
139
|
+
the page token, exact route, page identity and page origin. Use `authenticate` for
|
|
140
|
+
page identity and `authorize` for current permissions/session validity. Authorization
|
|
141
|
+
runs before commands, again after contract validation, and before render publication.
|
|
142
|
+
Revocation and disconnect cancel ownership even when validation is still running.
|
|
143
|
+
The page token is not a substitute for credentials.
|
|
144
|
+
|
|
145
|
+
Initial page attachment completes before custom initialization hooks or commands.
|
|
146
|
+
Do not call page commands from initialization hooks expecting those hooks themselves
|
|
147
|
+
to finish first. Each page owns its connection; the same token cannot attach twice.
|
|
148
|
+
|
|
149
|
+
Reconnect reauthenticates, invokes existing `connected()` hooks, and sends a fresh
|
|
150
|
+
rendering snapshot. Game-seat recovery remains in that server hook. Commands are
|
|
151
|
+
not queued or replayed. Page-session expiration requires a reload; game persistence
|
|
152
|
+
is not provided by page retention.
|
|
153
|
+
|
|
154
|
+
## Completion and client runtime
|
|
155
|
+
|
|
156
|
+
After successful handler dispatch, Redweb sends a correlated `redweb:result`.
|
|
157
|
+
The generated runtime waits specifically for that terminal type or a protocol error,
|
|
158
|
+
not intermediate correlated progress messages. Direct client users can opt into
|
|
159
|
+
the same behavior using `client.request(type, payload, { responseType })`; omitting
|
|
160
|
+
the option preserves the existing any-correlated-response behavior.
|
|
161
|
+
|
|
162
|
+
For an expected application rejection, send a safe correlated error with
|
|
163
|
+
`socket.sendProtocolError('GAME_REJECTED', safeMessage, { requestId })` and return
|
|
164
|
+
`false` from the handler. Only literal `false` declines successful dispatch;
|
|
165
|
+
`undefined` remains success. The browser shows error feedback, preserves the form,
|
|
166
|
+
and keeps its connection usable. Returning `false` without sending a correlated
|
|
167
|
+
reply leaves a requesting client waiting until its deadline. Unexpected exceptions
|
|
168
|
+
retain the existing sanitized handler-failure behavior and close the connection.
|
|
169
|
+
|
|
170
|
+
This browser support lives in redweb-client's existing feedback/transport modules.
|
|
171
|
+
The server still owns validation, authorization, game revisions, room fan-out and
|
|
172
|
+
private rendering. Disabled controls are presentation, never permissions.
|
|
@@ -1,120 +1,120 @@
|
|
|
1
|
-
# Socket-page release preparation
|
|
2
|
-
|
|
3
|
-
Updated 2026-09-02. The maintainer published client 0.3.0; no core publication or
|
|
4
|
-
hosting deployment was performed during this preparation.
|
|
5
|
-
|
|
6
|
-
## Client publication verified
|
|
7
|
-
|
|
8
|
-
`redweb-client@0.3.0` was published from the sibling client checkout on
|
|
9
|
-
`codex/socket-page-actions`, commit `3d2bcfec75db367b6e4924bcf430670f5569b1c7`.
|
|
10
|
-
Its package version and lockfile agree, release notes are included, and prepack
|
|
11
|
-
rebuilds the ESM/CommonJS bundles and declarations. Build logs use stderr so
|
|
12
|
-
`npm pack --json` remains machine-readable.
|
|
13
|
-
|
|
14
|
-
After npm's processing delay, the actual public registry returned version 0.3.0,
|
|
15
|
-
the same source commit, and the tested candidate integrity below. A fresh local
|
|
16
|
-
pack independently reproduced the publication's SHA-1
|
|
17
|
-
`def8dcc0bb205ccff68bf8fd1c7ea91b7d289547`, 14 files and 31,378 bytes.
|
|
18
|
-
|
|
19
|
-
```text
|
|
20
|
-
sha512-hUBa40wdsvWKY5bqeyreDzUhMcaB0e0x0OX+YRyZw6ccri6BBSHnM6eEKMV0wOkprIF2cxDkGNILwAA5ELYkWw==
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Core's real dependency installation now resolves that registry artifact, not a
|
|
24
|
-
link. Its lockfile records the actual registry URL and integrity. This verifies
|
|
25
|
-
artifact identity, not a claim that client provenance was available.
|
|
26
|
-
|
|
27
|
-
## Finish the dependent releases afterward
|
|
28
|
-
|
|
29
|
-
1. Completed: verify client 0.3.0 registry metadata and install the actual artifact.
|
|
30
|
-
2. Redweb **0.15.0** now has `redweb-client@^0.3.0`, its real npm lockfile,
|
|
31
|
-
versioned changelog and immutable 69-page 0.15.0 documentation snapshot.
|
|
32
|
-
The final gates below passed; core is ready for manual publication.
|
|
33
|
-
3. After core publication, update site/tutorial exact dependency pins and locks,
|
|
34
|
-
synchronize the released catalogue, run the downloadable-archive/browser gates,
|
|
35
|
-
then hand off manual Firebase deployment.
|
|
36
|
-
|
|
37
|
-
No future registry URL, integrity value or already-published version was fabricated
|
|
38
|
-
in a lockfile. The site's development tutorial remains undeployable with its
|
|
39
|
-
previous published pins; its candidate-archive tests are not evidence that core
|
|
40
|
-
0.15.0 is already published. Do not deploy it before step 3.
|
|
41
|
-
|
|
42
|
-
## Verification completed
|
|
43
|
-
|
|
44
|
-
- Client `npm test`: build, declarations, unit tests, mock-free HTTP/WS integration,
|
|
45
|
-
and headed Chrome passed. Original-source coverage remains 800 statements,
|
|
46
|
-
543 branches, 125 functions and 667 lines, all 100%. Report:
|
|
47
|
-
`coverage/client-source/af576edc-b382-424b-97a2-bd46ca163832/summary.json`.
|
|
48
|
-
- The actual client tarball installs in a fresh, unlinked application with released
|
|
49
|
-
Redweb 0.14.0. Both module formats and the optional live-html entry load; native
|
|
50
|
-
socket requests wait for terminal replies and preserve null payloads. Actual
|
|
51
|
-
nested HTTP form parsing and the installed Express/body-parser qs versions pass.
|
|
52
|
-
Run the opt-in regression with `REDWEB_VERIFY_CLIENT_RELEASE=1` and
|
|
53
|
-
`tests/integration/client-release.integration.test.js`; it rebuilds/packs the
|
|
54
|
-
sibling client and uses the existing owned-workspace/process helpers.
|
|
55
|
-
- After installing registry client 0.3.0, 308 core tests across 29 suites pass.
|
|
56
|
-
Every `src/htmx/*.js` module, `src/cli/templates.js`, and the socket
|
|
57
|
-
`BaseHandler`, `SocketContract`, `SocketAction` and `HandlerGuard` modules
|
|
58
|
-
reach 100% statements, branches, functions and lines. This is scoped coverage,
|
|
59
|
-
not whole-repository certification. Report: `coverage/socket-page-release`.
|
|
60
|
-
- Canonical examples, protocol declarations, all three TypeScript configurations,
|
|
61
|
-
generated documentation and the prepublication release check pass.
|
|
62
|
-
- The actual downloadable tutorial archive passes independent installation,
|
|
63
|
-
compilation, type tests, mock-free HTTP/WS/SQLite tests, all-four 100% coverage
|
|
64
|
-
of its game/schema modules, and headed Chrome acceptance. The explicit pair was
|
|
65
|
-
core 0.15.0 candidate plus a client 0.3.0 pack byte-identical to npm's artifact;
|
|
66
|
-
no developer links were used inside the extracted application. Its unchanged
|
|
67
|
-
old dependency pins still need replacement after core publication.
|
|
68
|
-
- Core's production audit reports zero vulnerabilities under its application-root
|
|
69
|
-
qs policy. The installed dependency signature audit verifies 428 registry
|
|
70
|
-
signatures and 31 attestations; this aggregate does not claim every package has
|
|
71
|
-
provenance.
|
|
72
|
-
- Fresh site/tutorial locked installs audit with zero reported vulnerabilities.
|
|
73
|
-
The site build, 438-page HTTP/link verification and its seven-module 100%
|
|
74
|
-
documentation coverage scope pass. After restoring npm links, the headed
|
|
75
|
-
three-player tutorial passes login, rejection/input retention, moves, reconnect,
|
|
76
|
-
disconnect presence, win and logout.
|
|
77
|
-
- The complete isolated core package gate passes against registry client 0.3.0
|
|
78
|
-
without a candidate-client override: headed counter/chat/cards/components/JSX,
|
|
79
|
-
private dashboard login and actions, reconnect/disconnect, all six generated
|
|
80
|
-
starters and source-free execution, executable documentation and static export.
|
|
81
|
-
Bundled Live HTML and browser-refresh coverage each remain all-four 100%.
|
|
82
|
-
Report: `coverage/packed-browser/2cc05d98-d6b7-4c54-b5ce-fef4cbb83053`.
|
|
83
|
-
The tested core archive SHA-256 was
|
|
84
|
-
`1fd3fe3b35fd8ec0f9e805df9c3ad6655af40f373e38b44ab0418db71660eb1a`;
|
|
85
|
-
the subsequent evidence-only update to this file changes the final archive hash,
|
|
86
|
-
not its runtime, recipes, declarations or versioned catalogue.
|
|
87
|
-
- The independent senior critic approved the release metadata, actual installed
|
|
88
|
-
client identity and catalogue consistency with no blocking findings. Core
|
|
89
|
-
publication dry run passes. No soak or long fixed-window tests were run.
|
|
90
|
-
|
|
91
|
-
## Manual next step
|
|
92
|
-
|
|
93
|
-
Publish from the clean `codex/socket-page-actions` core checkout:
|
|
94
|
-
|
|
95
|
-
```powershell
|
|
96
|
-
Set-Location C:\Users\arkam\Documents\redweb
|
|
97
|
-
$env:NODE_OPTIONS = '--use-system-ca'
|
|
98
|
-
npm publish
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
The system-trust-store option preserves TLS verification. Do not disable TLS
|
|
102
|
-
checks. Do not publish the client again or deploy the site yet. After core is
|
|
103
|
-
available in npm, replace the site's/tutorial's old pins with verified registry
|
|
104
|
-
dependencies and synchronize the 0.15.0 catalogue before rebuilding and deploying.
|
|
105
|
-
|
|
106
|
-
## Dependency mitigation, not a library-level promise
|
|
107
|
-
|
|
108
|
-
Core development, generated applications, the site and the tutorial now use an
|
|
109
|
-
application-root override scoped to the Express dependency subtree:
|
|
110
|
-
`{ "express": { "qs": "6.16.0" } }`. Their checked locks and the fresh packed-client
|
|
111
|
-
consumer audit report zero known vulnerabilities. Actual Express and body-parser
|
|
112
|
-
both resolve the patched qs version. The generator reuses the root policy rather
|
|
113
|
-
than maintaining a separate starter copy.
|
|
114
|
-
|
|
115
|
-
The override does not upgrade Express or affect unrelated dependency subtrees.
|
|
116
|
-
It also does **not** propagate from Redweb when another application installs it:
|
|
117
|
-
existing consumers must apply the documented root policy and verify their own
|
|
118
|
-
locks/tests. See [release trust](RELEASE_TRUST.md#temporary-express-4-dependency-mitigation)
|
|
119
|
-
for the maintainer advisories and npm's override rules. Ordinary installs without
|
|
120
|
-
the policy can remain affected until upstream dependency ranges are patched.
|
|
1
|
+
# Socket-page release preparation
|
|
2
|
+
|
|
3
|
+
Updated 2026-09-02. The maintainer published client 0.3.0; no core publication or
|
|
4
|
+
hosting deployment was performed during this preparation.
|
|
5
|
+
|
|
6
|
+
## Client publication verified
|
|
7
|
+
|
|
8
|
+
`redweb-client@0.3.0` was published from the sibling client checkout on
|
|
9
|
+
`codex/socket-page-actions`, commit `3d2bcfec75db367b6e4924bcf430670f5569b1c7`.
|
|
10
|
+
Its package version and lockfile agree, release notes are included, and prepack
|
|
11
|
+
rebuilds the ESM/CommonJS bundles and declarations. Build logs use stderr so
|
|
12
|
+
`npm pack --json` remains machine-readable.
|
|
13
|
+
|
|
14
|
+
After npm's processing delay, the actual public registry returned version 0.3.0,
|
|
15
|
+
the same source commit, and the tested candidate integrity below. A fresh local
|
|
16
|
+
pack independently reproduced the publication's SHA-1
|
|
17
|
+
`def8dcc0bb205ccff68bf8fd1c7ea91b7d289547`, 14 files and 31,378 bytes.
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
sha512-hUBa40wdsvWKY5bqeyreDzUhMcaB0e0x0OX+YRyZw6ccri6BBSHnM6eEKMV0wOkprIF2cxDkGNILwAA5ELYkWw==
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Core's real dependency installation now resolves that registry artifact, not a
|
|
24
|
+
link. Its lockfile records the actual registry URL and integrity. This verifies
|
|
25
|
+
artifact identity, not a claim that client provenance was available.
|
|
26
|
+
|
|
27
|
+
## Finish the dependent releases afterward
|
|
28
|
+
|
|
29
|
+
1. Completed: verify client 0.3.0 registry metadata and install the actual artifact.
|
|
30
|
+
2. Redweb **0.15.0** now has `redweb-client@^0.3.0`, its real npm lockfile,
|
|
31
|
+
versioned changelog and immutable 69-page 0.15.0 documentation snapshot.
|
|
32
|
+
The final gates below passed; core is ready for manual publication.
|
|
33
|
+
3. After core publication, update site/tutorial exact dependency pins and locks,
|
|
34
|
+
synchronize the released catalogue, run the downloadable-archive/browser gates,
|
|
35
|
+
then hand off manual Firebase deployment.
|
|
36
|
+
|
|
37
|
+
No future registry URL, integrity value or already-published version was fabricated
|
|
38
|
+
in a lockfile. The site's development tutorial remains undeployable with its
|
|
39
|
+
previous published pins; its candidate-archive tests are not evidence that core
|
|
40
|
+
0.15.0 is already published. Do not deploy it before step 3.
|
|
41
|
+
|
|
42
|
+
## Verification completed
|
|
43
|
+
|
|
44
|
+
- Client `npm test`: build, declarations, unit tests, mock-free HTTP/WS integration,
|
|
45
|
+
and headed Chrome passed. Original-source coverage remains 800 statements,
|
|
46
|
+
543 branches, 125 functions and 667 lines, all 100%. Report:
|
|
47
|
+
`coverage/client-source/af576edc-b382-424b-97a2-bd46ca163832/summary.json`.
|
|
48
|
+
- The actual client tarball installs in a fresh, unlinked application with released
|
|
49
|
+
Redweb 0.14.0. Both module formats and the optional live-html entry load; native
|
|
50
|
+
socket requests wait for terminal replies and preserve null payloads. Actual
|
|
51
|
+
nested HTTP form parsing and the installed Express/body-parser qs versions pass.
|
|
52
|
+
Run the opt-in regression with `REDWEB_VERIFY_CLIENT_RELEASE=1` and
|
|
53
|
+
`tests/integration/client-release.integration.test.js`; it rebuilds/packs the
|
|
54
|
+
sibling client and uses the existing owned-workspace/process helpers.
|
|
55
|
+
- After installing registry client 0.3.0, 308 core tests across 29 suites pass.
|
|
56
|
+
Every `src/htmx/*.js` module, `src/cli/templates.js`, and the socket
|
|
57
|
+
`BaseHandler`, `SocketContract`, `SocketAction` and `HandlerGuard` modules
|
|
58
|
+
reach 100% statements, branches, functions and lines. This is scoped coverage,
|
|
59
|
+
not whole-repository certification. Report: `coverage/socket-page-release`.
|
|
60
|
+
- Canonical examples, protocol declarations, all three TypeScript configurations,
|
|
61
|
+
generated documentation and the prepublication release check pass.
|
|
62
|
+
- The actual downloadable tutorial archive passes independent installation,
|
|
63
|
+
compilation, type tests, mock-free HTTP/WS/SQLite tests, all-four 100% coverage
|
|
64
|
+
of its game/schema modules, and headed Chrome acceptance. The explicit pair was
|
|
65
|
+
core 0.15.0 candidate plus a client 0.3.0 pack byte-identical to npm's artifact;
|
|
66
|
+
no developer links were used inside the extracted application. Its unchanged
|
|
67
|
+
old dependency pins still need replacement after core publication.
|
|
68
|
+
- Core's production audit reports zero vulnerabilities under its application-root
|
|
69
|
+
qs policy. The installed dependency signature audit verifies 428 registry
|
|
70
|
+
signatures and 31 attestations; this aggregate does not claim every package has
|
|
71
|
+
provenance.
|
|
72
|
+
- Fresh site/tutorial locked installs audit with zero reported vulnerabilities.
|
|
73
|
+
The site build, 438-page HTTP/link verification and its seven-module 100%
|
|
74
|
+
documentation coverage scope pass. After restoring npm links, the headed
|
|
75
|
+
three-player tutorial passes login, rejection/input retention, moves, reconnect,
|
|
76
|
+
disconnect presence, win and logout.
|
|
77
|
+
- The complete isolated core package gate passes against registry client 0.3.0
|
|
78
|
+
without a candidate-client override: headed counter/chat/cards/components/JSX,
|
|
79
|
+
private dashboard login and actions, reconnect/disconnect, all six generated
|
|
80
|
+
starters and source-free execution, executable documentation and static export.
|
|
81
|
+
Bundled Live HTML and browser-refresh coverage each remain all-four 100%.
|
|
82
|
+
Report: `coverage/packed-browser/2cc05d98-d6b7-4c54-b5ce-fef4cbb83053`.
|
|
83
|
+
The tested core archive SHA-256 was
|
|
84
|
+
`1fd3fe3b35fd8ec0f9e805df9c3ad6655af40f373e38b44ab0418db71660eb1a`;
|
|
85
|
+
the subsequent evidence-only update to this file changes the final archive hash,
|
|
86
|
+
not its runtime, recipes, declarations or versioned catalogue.
|
|
87
|
+
- The independent senior critic approved the release metadata, actual installed
|
|
88
|
+
client identity and catalogue consistency with no blocking findings. Core
|
|
89
|
+
publication dry run passes. No soak or long fixed-window tests were run.
|
|
90
|
+
|
|
91
|
+
## Manual next step
|
|
92
|
+
|
|
93
|
+
Publish from the clean `codex/socket-page-actions` core checkout:
|
|
94
|
+
|
|
95
|
+
```powershell
|
|
96
|
+
Set-Location C:\Users\arkam\Documents\redweb
|
|
97
|
+
$env:NODE_OPTIONS = '--use-system-ca'
|
|
98
|
+
npm publish
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The system-trust-store option preserves TLS verification. Do not disable TLS
|
|
102
|
+
checks. Do not publish the client again or deploy the site yet. After core is
|
|
103
|
+
available in npm, replace the site's/tutorial's old pins with verified registry
|
|
104
|
+
dependencies and synchronize the 0.15.0 catalogue before rebuilding and deploying.
|
|
105
|
+
|
|
106
|
+
## Dependency mitigation, not a library-level promise
|
|
107
|
+
|
|
108
|
+
Core development, generated applications, the site and the tutorial now use an
|
|
109
|
+
application-root override scoped to the Express dependency subtree:
|
|
110
|
+
`{ "express": { "qs": "6.16.0" } }`. Their checked locks and the fresh packed-client
|
|
111
|
+
consumer audit report zero known vulnerabilities. Actual Express and body-parser
|
|
112
|
+
both resolve the patched qs version. The generator reuses the root policy rather
|
|
113
|
+
than maintaining a separate starter copy.
|
|
114
|
+
|
|
115
|
+
The override does not upgrade Express or affect unrelated dependency subtrees.
|
|
116
|
+
It also does **not** propagate from Redweb when another application installs it:
|
|
117
|
+
existing consumers must apply the documented root policy and verify their own
|
|
118
|
+
locks/tests. See [release trust](RELEASE_TRUST.md#temporary-express-4-dependency-mitigation)
|
|
119
|
+
for the maintainer advisories and npm's override rules. Ordinary installs without
|
|
120
|
+
the policy can remain affected until upstream dependency ranges are patched.
|