redweb 0.15.0 → 0.16.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 +4 -1
- package/README.md +3 -3
- package/docs/CONNECTED_CLIENTS_VERIFICATION.md +65 -0
- package/docs/SOCKET_PAGES.md +73 -0
- package/docs/generated.json +217 -217
- package/docs/releases/0.16.0.json +2217 -0
- package/index.d.ts +51 -4
- package/index.js +7 -2
- package/package.json +1 -1
- package/src/ws/ConnectedClients.js +207 -0
- package/src/ws/RoomRegistry.js +4 -2
- package/src/ws/RouteRuntime.js +11 -7
- package/src/ws/SocketRoute.js +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.16.0
|
|
4
|
+
|
|
5
|
+
- Add opt-in `connectedClients` over the existing RoomRegistry: verified per-connection identity, synchronous room/domain joins with membership rollback, deduplicated presence and checked per-player page projection. Typed handlers bind without changing the browser-safe socket contract. Raw command completion is independent of state updates; only deliberate rejections expose text.
|
|
6
|
+
- Fence obsolete projection failures, bound asynchronous adapters by connection lifetime, and keep a failed recipient from rejecting another player's committed command. Add mock-free socket regressions and unit coverage; no client package changes are needed.
|
|
4
7
|
|
|
5
8
|
## 0.15.0
|
|
6
9
|
|
package/README.md
CHANGED
|
@@ -11,12 +11,12 @@ Redweb 0.14.0 adds [`defineApp({ pages, sockets, services, port })`](docs/APPLIC
|
|
|
11
11
|
Start with a complete, tested counter application:
|
|
12
12
|
|
|
13
13
|
<!-- redweb:setup:start -->
|
|
14
|
-
> Documentation for Redweb 0.
|
|
14
|
+
> Documentation for Redweb 0.16.0. Install that exact version when following these examples.
|
|
15
15
|
|
|
16
16
|
```sh
|
|
17
|
-
npx --yes redweb@0.
|
|
17
|
+
npx --yes redweb@0.16.0 init my-realtime --template realtime
|
|
18
18
|
cd my-realtime
|
|
19
|
-
npm install --save-exact redweb@0.
|
|
19
|
+
npm install --save-exact redweb@0.16.0
|
|
20
20
|
npm test
|
|
21
21
|
npm run dev
|
|
22
22
|
```
|
|
@@ -0,0 +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.
|
package/docs/SOCKET_PAGES.md
CHANGED
|
@@ -1,5 +1,78 @@
|
|
|
1
1
|
# Server-side TSX for custom socket routes
|
|
2
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
|
+
|
|
3
76
|
Added in Redweb 0.15.0 with redweb-client 0.3.0, installed automatically by Redweb.
|
|
4
77
|
Earlier Redweb 0.14.0/client 0.2.0 packages do not provide this extension.
|
|
5
78
|
Contributors editing both packages can use the optional npm-link workflow in the repository's `docs/CLIENT_DEVELOPMENT.md`.
|