redweb 0.14.0 → 0.15.0
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 +13 -3
- package/README.md +289 -276
- package/contract.d.ts +11 -3
- package/docs/CLI.md +1 -1
- package/docs/CLIENT_DEVELOPMENT.md +9 -5
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/GETTING_STARTED.md +1 -1
- package/docs/LIVE_HTML.md +2 -2
- package/docs/MIGRATION.md +1 -1
- package/docs/RELEASE_TRUST.md +29 -6
- package/docs/RUNTIME_DIAGNOSTICS.md +1 -1
- package/docs/SOCKET_CONTRACTS.md +6 -3
- package/docs/SOCKET_PAGES.md +99 -0
- package/docs/SOCKET_PAGE_RELEASE_PREPARATION.md +120 -0
- package/docs/SOCKET_PAGE_VERIFICATION.md +85 -0
- package/docs/generated.json +2217 -2208
- package/docs/releases/0.15.0.json +2217 -0
- package/docs/topics.json +2 -1
- package/index.d.ts +6 -2
- package/package.json +6 -3
- package/recipes/shared/README.md +7 -0
- package/src/cli/templates.js +3 -2
- package/src/htmx/Jsx.js +2 -2
- package/src/htmx/LiveHtmlServer.js +1 -1
- package/src/htmx/PageManager.js +10 -7
- package/src/htmx/PageSocketRoute.js +132 -0
- package/src/htmx/ReactiveRenderer.js +8 -2
- package/src/htmx/SocketAction.js +19 -0
- package/src/htmx/metadata.js +6 -2
- package/src/ws/BaseHandler.js +6 -4
- package/src/ws/HandlerGuard.js +4 -0
- package/src/ws/SocketAction.js +16 -0
- package/src/ws/SocketContract.js +3 -2
- package/src/ws/SocketRoute.js +3 -2
package/contract.d.ts
CHANGED
|
@@ -15,9 +15,17 @@ export interface SocketSchema<Input = unknown, Output = Input> {
|
|
|
15
15
|
export type SocketSchemas = Readonly<Record<string, SocketSchema>>;
|
|
16
16
|
export type ContractInput<Schema extends SocketSchema> = NonNullable<Schema['~standard']['types']>['input'];
|
|
17
17
|
export type ContractOutput<Schema extends SocketSchema> = Awaited<NonNullable<Schema['~standard']['types']>['output']>;
|
|
18
|
-
export type ContractMessage<Schemas extends SocketSchemas> = {
|
|
18
|
+
export type ContractMessage<Schemas extends SocketSchemas> = {
|
|
19
19
|
[Type in keyof Schemas & string]: ProtocolEnvelope<ContractOutput<Schemas[Type]>> & { type: Type };
|
|
20
|
-
}[keyof Schemas & string];
|
|
20
|
+
}[keyof Schemas & string];
|
|
21
|
+
|
|
22
|
+
declare const socketActionBrand: unique symbol;
|
|
23
|
+
export interface SocketAction { readonly [socketActionBrand]: true; }
|
|
24
|
+
export interface SocketHandler<Input> {
|
|
25
|
+
new (): BaseHandler;
|
|
26
|
+
/** Bind a JSON payload to a server-rendered rw-click/rw-submit control. */
|
|
27
|
+
with(payload: Input): SocketAction;
|
|
28
|
+
}
|
|
21
29
|
|
|
22
30
|
export interface ContractClient<Schemas extends SocketSchemas> {
|
|
23
31
|
envelope<Type extends keyof Schemas & string>(type: Type, payload: ContractInput<Schemas[Type]>, metadata?: ProtocolMetadata):
|
|
@@ -36,7 +44,7 @@ export interface SocketContract<Schemas extends SocketSchemas> {
|
|
|
36
44
|
handler<Type extends keyof Schemas & string>(type: Type, callback: (
|
|
37
45
|
socket: RedWebSocket, payload: ContractOutput<Schemas[Type]>,
|
|
38
46
|
message: ProtocolEnvelope<ContractOutput<Schemas[Type]>> & { type: Type },
|
|
39
|
-
) => unknown):
|
|
47
|
+
) => unknown): SocketHandler<ContractInput<Schemas[Type]>>;
|
|
40
48
|
client(socket: SendableSocket): ContractClient<Schemas>;
|
|
41
49
|
send<Type extends keyof Schemas & string>(socket: RedWebSocket, type: Type, payload: ContractInput<Schemas[Type]>, metadata?: ProtocolMetadata): Promise<boolean>;
|
|
42
50
|
}
|
package/docs/CLI.md
CHANGED
|
@@ -4,7 +4,7 @@ Use the version installed in your project (`npx --no-install redweb`) when troub
|
|
|
4
4
|
|
|
5
5
|
## Add pages, components, and socket routes
|
|
6
6
|
|
|
7
|
-
These commands are available in `redweb@0.
|
|
7
|
+
These commands are available in `redweb@0.15.0`.
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
10
|
npx --no-install redweb add page dashboard
|
|
@@ -1,12 +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.
|
|
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.
|
|
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).
|
|
10
14
|
|
|
11
15
|
## Link the sibling repositories
|
|
12
16
|
|
|
@@ -107,7 +111,7 @@ For example, from Redweb in PowerShell (use a fresh output directory):
|
|
|
107
111
|
npm --prefix ../redweb-client run build
|
|
108
112
|
New-Item -ItemType Directory -Path coverage/client-candidate
|
|
109
113
|
npm pack ../redweb-client --pack-destination coverage/client-candidate
|
|
110
|
-
$env:REDWEB_CLIENT_CANDIDATE = (Resolve-Path coverage/client-candidate/redweb-client-0.
|
|
114
|
+
$env:REDWEB_CLIENT_CANDIDATE = (Resolve-Path coverage/client-candidate/redweb-client-0.3.0.tgz).Path
|
|
111
115
|
npm run verify:live-html:package
|
|
112
116
|
Remove-Item Env:REDWEB_CLIENT_CANDIDATE
|
|
113
117
|
```
|
|
@@ -143,7 +147,7 @@ bundles with the source-tested local build and run the same browser checks.
|
|
|
143
147
|
A candidate pass is not a registry release pass. `npm run verify:package:tools` includes the fingerprint/containment
|
|
144
148
|
unit regressions; its scoped coverage is not coverage of every browser driver.
|
|
145
149
|
|
|
146
|
-
|
|
150
|
+
Historically, published `redweb-client@0.2.0` supplied both required entry points; version 0.1.0
|
|
147
151
|
does not. The 0.2.0 archive's runtime bundles match the previously source-tested
|
|
148
152
|
build, and the clean registry-installed package gate passes without an override.
|
|
149
153
|
The developer link can remain in place because registry checks own independent
|
package/docs/DEVELOPMENT.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Development refresh and inspection
|
|
2
2
|
|
|
3
|
-
This API is available in `redweb@0.
|
|
3
|
+
This API is available in `redweb@0.15.0`. Use documentation matching the installed package before enabling it.
|
|
4
4
|
|
|
5
5
|
## Browser refresh
|
|
6
6
|
|
package/docs/GETTING_STARTED.md
CHANGED
|
@@ -47,7 +47,7 @@ For private raw socket subscriptions, see [room authorization and shared request
|
|
|
47
47
|
|
|
48
48
|
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.
|
|
49
49
|
|
|
50
|
-
These deployment commands require a verified release pair. `redweb@0.
|
|
50
|
+
These deployment commands require a verified release pair. `redweb@0.15.0` 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.
|
|
51
51
|
|
|
52
52
|
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).
|
|
53
53
|
|
package/docs/LIVE_HTML.md
CHANGED
|
@@ -340,7 +340,7 @@ The same bounded validation implementation is shared with socket contracts. Thei
|
|
|
340
340
|
|
|
341
341
|
## Action authorization
|
|
342
342
|
|
|
343
|
-
Identity and permission are separate: the server's existing `authenticate(request)` hook establishes `context.principal`; an action policy decides whether that identity may perform this operation. In Redweb 0.
|
|
343
|
+
Identity and permission are separate: the server's existing `authenticate(request)` hook establishes `context.principal`; an action policy decides whether that identity may perform this operation. In Redweb 0.15.0, add `authorize` to the action decorator instead of repeating permission checks inside each method:
|
|
344
344
|
|
|
345
345
|
```tsx
|
|
346
346
|
// Inside a page/component; `input` is the amount schema from the example above.
|
|
@@ -365,7 +365,7 @@ Denial returns recoverable `ACCESS_DENIED`; timeout returns `ACCESS_TIMEOUT`; co
|
|
|
365
365
|
|
|
366
366
|
## Protected pages and shared request identity
|
|
367
367
|
|
|
368
|
-
In Redweb 0.
|
|
368
|
+
In Redweb 0.15.0, a page can declare `authorize(context)` alongside its route. This is an API pattern for an application that already supplies the server's `authenticate(request)` hook, not a standalone login system:
|
|
369
369
|
|
|
370
370
|
```tsx
|
|
371
371
|
@page('/account/:id', {
|
package/docs/MIGRATION.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Upgrade an existing Redweb application
|
|
2
2
|
|
|
3
|
-
Match the installed package to its versioned documentation. Redweb 0.
|
|
3
|
+
Match the installed package to its versioned documentation. Redweb 0.15.0 contains the capabilities described by the 0.15.0 guides; a later development checkout may not match that release. See [release verification](RELEASE_TRUST.md) and the changelog shipped with your selected package. Keep your lockfile and rollback artifact, and run your own real HTTP/WebSocket/browser tests after upgrading.
|
|
4
4
|
|
|
5
5
|
## 0.8 migration notes
|
|
6
6
|
|
package/docs/RELEASE_TRUST.md
CHANGED
|
@@ -16,20 +16,43 @@ Redweb is a Node.js HTTP/WebSocket library with server-rendered TSX, not a hoste
|
|
|
16
16
|
|
|
17
17
|
Use the [official Node release schedule](https://nodejs.org/en/about/previous-releases) for maintained releases, the [TypeScript decorator documentation](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#decorators) for the distinction between decorator modes, and [Node's TypeScript limitations](https://nodejs.org/api/typescript.html) for native execution constraints. Current per-commit test evidence and uncompleted checks are recorded in the [release checklist](AGENT_READY_ACCEPTANCE.md), not inferred from this table.
|
|
18
18
|
|
|
19
|
-
## Pin the package and the documentation together
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
## Pin the package and the documentation together
|
|
20
|
+
|
|
21
|
+
### Temporary Express 4 dependency mitigation
|
|
22
|
+
|
|
23
|
+
As verified on 2026-09-02, Express 4.22.2 selects `qs ~6.15.1`; the maintainer's
|
|
24
|
+
[isBuffer advisory](https://github.com/ljharb/qs/security/advisories/GHSA-4mjr-xmp4-gh2g)
|
|
25
|
+
and [bracket-key advisory](https://github.com/ljharb/qs/security/advisories/GHSA-x5fp-wj9c-mxmx)
|
|
26
|
+
identify patched `qs@6.16.0`. Until compatible upstream ranges select that fix,
|
|
27
|
+
use this temporary mitigation in the **application's root** `package.json`:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{ "overrides": { "express": { "qs": "6.16.0" } } }
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Merge it with existing overrides, run `npm install`, commit the resulting lockfile,
|
|
34
|
+
and verify with `npm ls qs`, `npm audit --omit=dev`, and application HTTP/form tests.
|
|
35
|
+
New generated starters include the same policy. It is scoped to Express so it
|
|
36
|
+
does not force unrelated dependency trees onto another `qs` version.
|
|
37
|
+
|
|
38
|
+
This is an application-level mitigation, not a transparent fix for every Redweb
|
|
39
|
+
consumer. [npm ignores overrides inside installed dependencies](https://docs.npmjs.com/cli/v11/configuring-npm/package-json/#overrides).
|
|
40
|
+
An ordinary installation without this root policy can still select affected
|
|
41
|
+
dependencies. No Express 5 migration, bundled fork or published shrinkwrap is
|
|
42
|
+
introduced. Audit results remain time-sensitive and application-specific.
|
|
43
|
+
|
|
44
|
+
For a published application, select an exact release, commit its lockfile, and use `npm ci` in CI/deployment. This guide is versioned for 0.15.0. Before registry publication, verify the packed candidate; after publication, repeat these registry checks from a clean application:
|
|
22
45
|
|
|
23
46
|
```sh
|
|
24
|
-
npm view redweb@0.
|
|
25
|
-
npm install --save-exact redweb@0.
|
|
47
|
+
npm view redweb@0.15.0 version engines dist.integrity dist.signatures dist.attestations gitHead --json
|
|
48
|
+
npm install --save-exact redweb@0.15.0
|
|
26
49
|
npm audit signatures
|
|
27
50
|
npm audit --omit=dev
|
|
28
51
|
```
|
|
29
52
|
|
|
30
53
|
The signature command must run in the installed application directory. Keep TLS verification enabled and use a current npm CLI; a certificate/trust-store failure is not a reason to disable verification. A lockfile's integrity value detects changed package bytes; registry signatures authenticate registry metadata; provenance, when present and verified, links an artifact to a build/source identity. Vulnerability audit is a separate check against known advisories, not an application penetration test.
|
|
31
54
|
|
|
32
|
-
Redweb 0.
|
|
55
|
+
Redweb 0.15.0 contains socket-bound TSX controls and connection-owned page state, unified application startup, server-rendered TSX, reactive state/actions, complete starters, shared socket contracts, authorization, diagnostics, lifecycle work, and bounded heartbeat grace described by these versioned guides. Keep the package and documentation version aligned; do not mix a development guide or a future checkout with 0.15.0 and assume newer APIs exist.
|
|
33
56
|
|
|
34
57
|
Redweb is pre-1.0. Consult the changelog and versioned guide before upgrading, run your own real HTTP/WebSocket/browser tests, and keep a rollback artifact. Patch/minor numbers and a compatible TypeScript build alone do not prove wire compatibility, preserved sessions, database compatibility or application authorization. HTTP-created live-page sessions are process-owned; a restart or rolling replacement does not migrate them automatically. Raw socket protocol versions are negotiated only when the route opts in, and application payload compatibility remains your contract.
|
|
35
58
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Understand failures before retrying
|
|
2
2
|
|
|
3
|
-
Status: included in `redweb@0.
|
|
3
|
+
Status: included in `redweb@0.15.0`.
|
|
4
4
|
|
|
5
5
|
Authentication identifies a visitor. Authorization decides what that visitor may do. Validation checks an input's shape. An application failure means server code or a dependency failed; it is not evidence that the visitor supplied bad credentials.
|
|
6
6
|
|
package/docs/SOCKET_CONTRACTS.md
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
# Shared socket contracts
|
|
2
2
|
|
|
3
|
-
Status: included in `redweb@0.
|
|
3
|
+
Status: included in `redweb@0.15.0`.
|
|
4
4
|
|
|
5
5
|
A contract declares message payloads once. The same schema supplies runtime validation and inferred TypeScript types for senders and handlers. The URL still selects the route (`/match`), and the envelope's `type` selects an individual handler (`join`, `move`, `resume`). No socket decorators or second action dispatcher are required.
|
|
6
6
|
|
|
7
|
-
Start with `npx --yes redweb@0.
|
|
7
|
+
Start with `npx --yes redweb@0.15.0 init my-match --template socket`. The complete maintained example lives in [the socket recipe](../recipes/socket/README.md): [contract](../recipes/socket/contract.ts), [handlers](../recipes/socket/handlers.ts), [server](../recipes/socket/app.tsx), and [real-network tests](../recipes/socket/app.test.cjs).
|
|
8
8
|
|
|
9
9
|
Session ownership is separate from room fan-out. For authenticated group delivery,
|
|
10
10
|
see [room authorization](ROOM_AUTHORIZATION.md) and the complete
|
|
11
11
|
[shared page/private-room example](snippets/room-access.tsx).
|
|
12
12
|
|
|
13
|
-
## One schema, two sides
|
|
13
|
+
## One schema, two sides
|
|
14
|
+
|
|
15
|
+
Redweb 0.15.0 also supports [typed handlers in server TSX](SOCKET_PAGES.md)
|
|
16
|
+
with per-connection page state; earlier releases do not include that extension.
|
|
14
17
|
|
|
15
18
|
Import `defineSocketContract` from `redweb/contract` for a shared module, or from `redweb` in server-only code. The standalone entry does not import the HTTP server or Node socket listener. Browser consumers need a bundler capable of consuming the CommonJS package; this is not a native browser script URL or a React integration.
|
|
16
19
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Server-side TSX for custom socket routes
|
|
2
|
+
|
|
3
|
+
Added in Redweb 0.15.0 with redweb-client 0.3.0, installed automatically by Redweb.
|
|
4
|
+
Earlier Redweb 0.14.0/client 0.2.0 packages do not provide this extension.
|
|
5
|
+
Contributors editing both packages can use the optional npm-link workflow in the repository's `docs/CLIENT_DEVELOPMENT.md`.
|
|
6
|
+
|
|
7
|
+
A live page can attach to a registered custom `SocketRoute` using
|
|
8
|
+
`@page('/', { socket: MatchRoute })`. There is no new view class, no second renderer,
|
|
9
|
+
and no application-specific browser module. Its connection carries ordinary typed
|
|
10
|
+
commands and reserved `redweb:*` rendering/completion messages.
|
|
11
|
+
|
|
12
|
+
## Typed controls
|
|
13
|
+
|
|
14
|
+
`defineSocketContract(...).handler(type, callback)` still returns a handler class.
|
|
15
|
+
That class can now be used as a JSX binding:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
<form rw-submit={Join}>
|
|
19
|
+
<input name="room" required />
|
|
20
|
+
<button>Join room</button>
|
|
21
|
+
</form>
|
|
22
|
+
|
|
23
|
+
<button rw-click={Move.with({ cell, revision })}>Move</button>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`.with()` snapshots JSON data; it never invokes the handler during rendering.
|
|
27
|
+
TypeScript checks the payload's input type. Incoming wire data is independently
|
|
28
|
+
validated by the contract, including asynchronous schemas. Form fields merge over
|
|
29
|
+
the bound object payload. A click sends its bound payload, or an empty object when
|
|
30
|
+
none was supplied. Bound values are untrusted inputs, not server-held secrets or
|
|
31
|
+
authorization capabilities. Do not embed private data in them.
|
|
32
|
+
|
|
33
|
+
Bindings are server-owned identities, not arbitrary function closures. Rendering
|
|
34
|
+
rejects references to handlers absent from the attached route, even if a different
|
|
35
|
+
handler has the same message name. Existing string `rw-click`/`rw-submit` actions
|
|
36
|
+
remain unchanged on ordinary live pages. Socket-bound pages dispatch only their
|
|
37
|
+
custom route handlers; do not mix local `@action()`/`rw-bind` commands into them.
|
|
38
|
+
|
|
39
|
+
## Server-owned client state
|
|
40
|
+
|
|
41
|
+
On an attached connection, `socket.page(PageClass)` returns that connection's
|
|
42
|
+
concrete page after checking its class, ownership and active lifetime:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
if (socket.page) {
|
|
46
|
+
socket.page(GamePage).game = games.snapshot(room, account);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Assigning `@state()` fields uses the existing reactive renderer and keyed TSX.
|
|
51
|
+
Raw connections have no `page` accessor and keep their existing socket protocol.
|
|
52
|
+
Shared domain state belongs in a room/service; each private page receives only its
|
|
53
|
+
authorized perspective. Components remain ordinary page-owned Redweb components.
|
|
54
|
+
|
|
55
|
+
## Configuration and boundaries
|
|
56
|
+
|
|
57
|
+
Register the route once in `defineApp({ pages: [GamePage], sockets: [MatchRoute] })`.
|
|
58
|
+
Socket-bound pages must be live, connection-scoped and render TSX. Their route must
|
|
59
|
+
support protocol version `1` with the default `redwebVersion` query parameter and
|
|
60
|
+
explicitly allow duplicate connections (independent tabs). `redweb:*` handler names
|
|
61
|
+
are reserved. Page-enabled routes use ordered, bounded message dispatch and track
|
|
62
|
+
in-flight work for shutdown. JSON commands are supported; binary input is rejected
|
|
63
|
+
on page-attached connections. Raw route connections retain binary handling.
|
|
64
|
+
|
|
65
|
+
The adapter preserves route admission, origin and placement policies, then checks
|
|
66
|
+
the page token, exact route, page identity and page origin. Use `authenticate` for
|
|
67
|
+
page identity and `authorize` for current permissions/session validity. Authorization
|
|
68
|
+
runs before commands, again after contract validation, and before render publication.
|
|
69
|
+
Revocation and disconnect cancel ownership even when validation is still running.
|
|
70
|
+
The page token is not a substitute for credentials.
|
|
71
|
+
|
|
72
|
+
Initial page attachment completes before custom initialization hooks or commands.
|
|
73
|
+
Do not call page commands from initialization hooks expecting those hooks themselves
|
|
74
|
+
to finish first. Each page owns its connection; the same token cannot attach twice.
|
|
75
|
+
|
|
76
|
+
Reconnect reauthenticates, invokes existing `connected()` hooks, and sends a fresh
|
|
77
|
+
rendering snapshot. Game-seat recovery remains in that server hook. Commands are
|
|
78
|
+
not queued or replayed. Page-session expiration requires a reload; game persistence
|
|
79
|
+
is not provided by page retention.
|
|
80
|
+
|
|
81
|
+
## Completion and client runtime
|
|
82
|
+
|
|
83
|
+
After successful handler dispatch, Redweb sends a correlated `redweb:result`.
|
|
84
|
+
The generated runtime waits specifically for that terminal type or a protocol error,
|
|
85
|
+
not intermediate correlated progress messages. Direct client users can opt into
|
|
86
|
+
the same behavior using `client.request(type, payload, { responseType })`; omitting
|
|
87
|
+
the option preserves the existing any-correlated-response behavior.
|
|
88
|
+
|
|
89
|
+
For an expected application rejection, send a safe correlated error with
|
|
90
|
+
`socket.sendProtocolError('GAME_REJECTED', safeMessage, { requestId })` and return
|
|
91
|
+
`false` from the handler. Only literal `false` declines successful dispatch;
|
|
92
|
+
`undefined` remains success. The browser shows error feedback, preserves the form,
|
|
93
|
+
and keeps its connection usable. Returning `false` without sending a correlated
|
|
94
|
+
reply leaves a requesting client waiting until its deadline. Unexpected exceptions
|
|
95
|
+
retain the existing sanitized handler-failure behavior and close the connection.
|
|
96
|
+
|
|
97
|
+
This browser support lives in redweb-client's existing feedback/transport modules.
|
|
98
|
+
The server still owns validation, authorization, game revisions, room fan-out and
|
|
99
|
+
private rendering. Disabled controls are presentation, never permissions.
|
|
@@ -0,0 +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.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Socket-bound TSX verification
|
|
2
|
+
|
|
3
|
+
Development verification on 2026-09-02, Windows, Node 22.21.0, headed Chrome 152.
|
|
4
|
+
This records feature acceptance, not an npm release or full-repository certification.
|
|
5
|
+
|
|
6
|
+
## Implementation and review
|
|
7
|
+
|
|
8
|
+
Core/client branch: `codex/socket-page-actions`. Site branch:
|
|
9
|
+
`codex/server-tsx-tutorial` in the sibling landing-page checkout.
|
|
10
|
+
|
|
11
|
+
- Typed handler references and `.with(payload)` reuse contract validation, page
|
|
12
|
+
ownership, reactive rendering and the existing redweb-client runtime.
|
|
13
|
+
- The tutorial has no application browser module or bundling step. Its private
|
|
14
|
+
page, game rules, commands, room fan-out and seat recovery live on the server.
|
|
15
|
+
- Independent critic reviews covered core/client and the actual tutorial. Fixed
|
|
16
|
+
findings included attachment ordering, post-validation disconnect authorization,
|
|
17
|
+
duplicate-connection policy, intermediate reply correlation, obsolete render
|
|
18
|
+
cancellation and rejected forms incorrectly reporting success. Final review
|
|
19
|
+
reported no remaining blocking findings within that scope.
|
|
20
|
+
|
|
21
|
+
## Passing gates
|
|
22
|
+
|
|
23
|
+
- 294 tests / 27 suites passed in the rendering regression selection below.
|
|
24
|
+
Every module in `src/htmx/*.js`, plus `BaseHandler`, `SocketContract`,
|
|
25
|
+
`SocketAction` and `HandlerGuard`, reached 100% statements, branches, functions
|
|
26
|
+
and lines. The changed explicit-false dispatch in `SocketRoute` is exercised by
|
|
27
|
+
real-network tests; this measurement does not claim all of `SocketRoute` or the
|
|
28
|
+
whole repository is covered by this selection.
|
|
29
|
+
- Client `npm test` passed linkage, build, declarations and the combined original
|
|
30
|
+
source gate: 800 statements, 543 branches, 125 functions and 667 lines, all 100%.
|
|
31
|
+
Report: `coverage/client-source/c819157b-6aaa-4020-99f4-152b8df473ed/summary.json`.
|
|
32
|
+
It runs plain and instrumented Node tests and headed Chrome on real HTTP/WS.
|
|
33
|
+
The existing instrumentation does not count every optional-chain/V8 branch.
|
|
34
|
+
- Core pretest checked canonical example output, protocol declarations, all
|
|
35
|
+
TypeScript configurations and 69 generated unreleased documentation pages.
|
|
36
|
+
The standalone contract entry also bundled for browsers without Node builtins.
|
|
37
|
+
- Site build and real HTTP verification passed: 438 pages, 11 examples, 30 API
|
|
38
|
+
articles, downloads and internal links. The seven-module documentation coverage
|
|
39
|
+
scope remains 100% lines, branches and functions.
|
|
40
|
+
- The actual tutorial archive was extracted to a fresh temporary directory,
|
|
41
|
+
installed with both explicitly packed development candidates (no links),
|
|
42
|
+
compiled, typechecked and tested with real HTTP, WebSockets and SQLite. Its
|
|
43
|
+
game-rule and message-schema modules remain all-four 100%; this is not a
|
|
44
|
+
whole-tutorial/authentication coverage claim.
|
|
45
|
+
- Headed Chrome passed both linked and extracted-package tutorial acceptance:
|
|
46
|
+
hello world, two-tab server counter, wrong/right login, two-player game,
|
|
47
|
+
third-player full-room rejection with retained input and reusable connection,
|
|
48
|
+
reconnect without move replay, disconnect presence, win and logout. Actual
|
|
49
|
+
outgoing game connections use `/match`; game commands are `join` and `move`.
|
|
50
|
+
- Headed static-site navigation passed both minimal homepage examples, six
|
|
51
|
+
highlighted chapters, next links and the project download.
|
|
52
|
+
|
|
53
|
+
New integration tests use actual transports, not mocks. Pure failure-boundary
|
|
54
|
+
units supplement them. No soak or long fixed-window workload was run.
|
|
55
|
+
|
|
56
|
+
### Reproduce the scoped core coverage gate
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
node node_modules/jest/bin/jest.js tests/htmx tests/ws tests/unit/socket-action.unit.test.js tests/unit/page-access.unit.test.js tests/unit/socket-contract.unit.test.js tests/unit/utilities.unit.test.js tests/unit/action-input.unit.test.js tests/unit/inspection.unit.test.js tests/unit/development-refresh.unit.test.js tests/unit/development-refresh-boundaries.unit.test.js tests/unit/development-refresh-cleanup.unit.test.js tests/unit/define-app.unit.test.js tests/integration/define-app.integration.test.js tests/integration/socket-page.integration.test.js tests/integration/socket-contract.integration.test.js tests/integration/live-html.integration.test.js tests/integration/page-access.integration.test.js tests/integration/action-input.integration.test.js tests/integration/inspection.integration.test.js --runInBand --silent --coverage --collectCoverageFrom=src/htmx/*.js --collectCoverageFrom=src/ws/BaseHandler.js --collectCoverageFrom=src/ws/SocketContract.js --collectCoverageFrom=src/ws/SocketAction.js --collectCoverageFrom=src/ws/HandlerGuard.js --coverageDirectory=coverage/socket-page-regression
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The site README documents the two candidate-tarball environment variables for
|
|
63
|
+
`npm test`. That gate includes headed browser acceptance inside the extracted
|
|
64
|
+
archive; Chrome and the tutorial's Node version are required.
|
|
65
|
+
|
|
66
|
+
## Release boundaries and outstanding dependency audit
|
|
67
|
+
|
|
68
|
+
The follow-up [release preparation](SOCKET_PAGE_RELEASE_PREPARATION.md) prepares
|
|
69
|
+
client 0.3.0 and records the tested application-root qs mitigation. The initial
|
|
70
|
+
observations below remain historical; they do not override that later status.
|
|
71
|
+
|
|
72
|
+
The old published versions (Redweb 0.14.0/client 0.2.0) do not contain these APIs.
|
|
73
|
+
Local tarballs retaining those development metadata versions were verification
|
|
74
|
+
inputs, not artifacts to publish over existing releases. Release a new client,
|
|
75
|
+
align and release Redweb, then update the site's tutorial pins/lockfile and
|
|
76
|
+
catalogue before manual deployment. Existing immutable release snapshots were
|
|
77
|
+
not rewritten. Nothing was published or deployed during this task.
|
|
78
|
+
|
|
79
|
+
An additional `npm audit --omit=dev` check reports four moderate dependency-tree
|
|
80
|
+
entries in the existing site/tutorial locks, rooted in two `qs` advisories:
|
|
81
|
+
[bracket-key parsing](https://github.com/advisories/GHSA-x5fp-wj9c-mxmx) and
|
|
82
|
+
[attacker-controlled isBuffer](https://github.com/advisories/GHSA-4mjr-xmp4-gh2g).
|
|
83
|
+
The installed Express 4 dependency range does not select the published qs 6.16.0
|
|
84
|
+
fix. This feature work does not waive that audit or silently force an Express 5
|
|
85
|
+
migration. Resolve and verify the dependency policy before production release.
|