@4xeoz/re-entry 0.2.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/README.md +337 -0
- package/node_modules/@webmcp-challenge/reentry-core/README.md +112 -0
- package/node_modules/@webmcp-challenge/reentry-core/package.json +38 -0
- package/node_modules/@webmcp-challenge/reentry-core/protocol/test-vectors/v0.1.json +47 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/agent-adapter.mjs +438 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/cloud-receiver-http.mjs +268 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/host-sdk.mjs +278 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/index.mjs +3 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/local-connector-client.mjs +530 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/managed-context-adapter.mjs +275 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/protocol.mjs +845 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/receiver-core.mjs +867 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/receiver-delivery.mjs +613 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/receiver-http-contract.mjs +24 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/receiver-support.mjs +151 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/sqlite-receiver-schema.mjs +184 -0
- package/node_modules/@webmcp-challenge/reentry-core/src/sqlite-receiver-store.mjs +573 -0
- package/package.json +44 -0
- package/src/browser-prompt.mjs +18 -0
- package/src/codex-discovery.mjs +246 -0
- package/src/codex-exec-adapter.mjs +197 -0
- package/src/codex-queue-adapter.mjs +214 -0
- package/src/credentials.mjs +87 -0
- package/src/index.mjs +6 -0
- package/src/local-connector.mjs +82 -0
- package/src/macos-service.mjs +184 -0
- package/src/main.mjs +733 -0
- package/src/pairing-client.mjs +545 -0
- package/src/terminal-ui.mjs +99 -0
package/README.md
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# Re-entry Local Connector
|
|
2
|
+
|
|
3
|
+
Install it once on the Mac where Codex should open; after one browser approval, a macOS
|
|
4
|
+
LaunchAgent keeps the outbound Connector running at login.
|
|
5
|
+
|
|
6
|
+
> Current boundary: this is a verified macOS Connector preview with a publish-ready npm package.
|
|
7
|
+
> It starts a fresh `codex exec` process with bounded context; it does not prove Browser/WebMCP
|
|
8
|
+
> attachment or final Host effects.
|
|
9
|
+
|
|
10
|
+
## One-time install
|
|
11
|
+
|
|
12
|
+
Requirements: macOS, Node.js 24+, Codex installed and signed in, and an absolute project directory
|
|
13
|
+
Codex may read and write.
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npx @4xeoz/re-entry install --codex-cd /absolute/path/to/your/project
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The published package uses the hosted Receiver by default. Use `--receiver` only when testing a
|
|
20
|
+
different Receiver, such as the local preview:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npx @4xeoz/re-entry install \
|
|
24
|
+
--receiver http://127.0.0.1:43224 \
|
|
25
|
+
--codex-cd /absolute/path/to/your/project
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`re-entry install` performs the whole user setup:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
check Node + find Codex + validate project directory
|
|
32
|
+
-> request a device authorization from Re-entry
|
|
33
|
+
-> show the verification URL and wait for the user to press Enter
|
|
34
|
+
-> open Re-entry in the default browser
|
|
35
|
+
-> sign in or create an account
|
|
36
|
+
-> approve this Mac once
|
|
37
|
+
-> save the device credential with mode 0600
|
|
38
|
+
-> install and start a per-user macOS LaunchAgent
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The Connector opens no local port and accepts no inbound connection. It polls Re-entry over an
|
|
42
|
+
outbound HTTPS connection in a deployed system; loopback HTTP is accepted only by the local
|
|
43
|
+
preview.
|
|
44
|
+
|
|
45
|
+
## Check it
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
re-entry status
|
|
49
|
+
re-entry --help
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The status view checks the local authorization, background job, Receiver reachability, Node, and
|
|
53
|
+
Codex. Useful development commands are:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
re-entry doctor --codex-cd /absolute/path/to/project
|
|
57
|
+
re-entry connect --receiver http://127.0.0.1:43224
|
|
58
|
+
re-entry claim-once --codex-cd /absolute/path/to/project
|
|
59
|
+
re-entry start --codex-cd /absolute/path/to/project
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`connect` repeats only account authorization. `install` is the normal product path because it also
|
|
63
|
+
installs the background job. `claim-once` is the smallest manual delivery test. The legacy
|
|
64
|
+
Host-code `pair` command remains only for compatibility tests.
|
|
65
|
+
|
|
66
|
+
## Give this to a coding agent
|
|
67
|
+
|
|
68
|
+
Copy this prompt into a coding-agent task:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
Install the Re-entry Local Connector on this Mac. First read the package README. Verify Node.js 24
|
|
72
|
+
or newer and locate the installed Codex executable. Run `npx @4xeoz/re-entry install` with an absolute
|
|
73
|
+
project directory. Let the human complete the Re-entry
|
|
74
|
+
browser approval; never copy browser cookies, organization keys, Connector tokens, or private keys
|
|
75
|
+
into chat, logs, source files, or git. Finish by running `re-entry status` and report the bounded
|
|
76
|
+
results without claiming Browser/WebMCP or production deployment.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Package map
|
|
80
|
+
|
|
81
|
+
- `src/main.mjs` — `re-entry` CLI and long-running poll loop.
|
|
82
|
+
- `src/pairing-client.mjs` — account-first browser device authorization.
|
|
83
|
+
- `src/credentials.mjs` — atomic local credential storage.
|
|
84
|
+
- `src/macos-service.mjs` — per-user LaunchAgent install and status.
|
|
85
|
+
- `src/local-connector.mjs` — one claim and activation boundary.
|
|
86
|
+
- `src/codex-exec-adapter.mjs` — fresh local Codex process adapter.
|
|
87
|
+
- `src/terminal-ui.mjs` — dependency-free human CLI presentation.
|
|
88
|
+
|
|
89
|
+
Verify the package with Node 24:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
npm run verify
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
<details>
|
|
96
|
+
<summary>Historical Host-code pairing notes</summary>
|
|
97
|
+
|
|
98
|
+
The material below describes the older Host-issued pairing-code preview. It remains for protocol
|
|
99
|
+
traceability but is not the current account-first install path.
|
|
100
|
+
|
|
101
|
+
The Local Connector is one outbound-only Node.js process. It polls the Cloud Receiver for one
|
|
102
|
+
short delivery lease, starts one fresh local Codex process, and then exits. It is not a web server,
|
|
103
|
+
does not open a port on the user's Mac, and does not accept inbound connections from the Receiver.
|
|
104
|
+
|
|
105
|
+
This is a local preview, not a background daemon or a production Agent integration.
|
|
106
|
+
|
|
107
|
+
## What must be installed
|
|
108
|
+
|
|
109
|
+
The current package is kept inside this repository, so install the repository first:
|
|
110
|
+
|
|
111
|
+
1. macOS;
|
|
112
|
+
2. Node.js 24 or newer;
|
|
113
|
+
3. the ChatGPT/Codex application or a `codex` executable available on `PATH`;
|
|
114
|
+
4. a Host project directory that the local Codex process can read and write; and
|
|
115
|
+
5. a reachable Receiver origin. `http://127.0.0.1` is allowed only for the local preview; a
|
|
116
|
+
Receiver on another machine must use HTTPS.
|
|
117
|
+
|
|
118
|
+
From a clean checkout:
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
git clone <repository-url>
|
|
122
|
+
cd OpenAI-Web-MCP-Challenge/runtime/local-connector
|
|
123
|
+
npm install
|
|
124
|
+
npm run verify
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The package bundles the reusable `@webmcp-challenge/reentry-core` modules it imports. It can be
|
|
128
|
+
installed from npm without a checked-out repository or a local `file:` dependency at runtime.
|
|
129
|
+
|
|
130
|
+
## Publish the package
|
|
131
|
+
|
|
132
|
+
The package name is `@4xeoz/re-entry` and the core is included in the tarball. After signing in to
|
|
133
|
+
the npm account that owns the `4xeoz` scope, publish from this directory:
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
npm login
|
|
137
|
+
npm publish --access public
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
After publishing, users run `npx @4xeoz/re-entry install`. The executable inside the package is
|
|
141
|
+
still named `re-entry`.
|
|
142
|
+
|
|
143
|
+
## Check a Mac before pairing
|
|
144
|
+
|
|
145
|
+
Run the read-only readiness check before connecting the machine:
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
npm run doctor -- \
|
|
149
|
+
--codex-cd "$HOME/Code/my-host-project"
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`doctor` checks Node.js, finds Codex, runs `codex --version`, and checks that the Host directory
|
|
153
|
+
exists and is readable and writable. In a terminal it shows each check; with `--json` or piped
|
|
154
|
+
stdout it prints a bounded `connector_ready` JSON event when ready.
|
|
155
|
+
|
|
156
|
+
Codex lookup order is:
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
--codex-binary
|
|
160
|
+
-> CODEX_BINARY
|
|
161
|
+
-> codex on PATH
|
|
162
|
+
-> common macOS command directories
|
|
163
|
+
-> ChatGPT.app/Codex.app in /Applications or ~/Applications
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
If Codex is installed in a non-standard location, configure it without changing source:
|
|
167
|
+
|
|
168
|
+
```sh
|
|
169
|
+
npm run doctor -- \
|
|
170
|
+
--codex-binary "/path/to/codex" \
|
|
171
|
+
--codex-cd "$HOME/Code/my-host-project"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The same `--codex-binary` and `--codex-cd` values are used by `claim-once`.
|
|
175
|
+
|
|
176
|
+
## Start with the guided CLI
|
|
177
|
+
|
|
178
|
+
For a human using the terminal, the simplest entry point is:
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
npm start -- \
|
|
182
|
+
--receiver http://127.0.0.1:43218 \
|
|
183
|
+
--codex-cd "$HOME/Code/my-host-project"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
On the first run, the Connector checks the Mac, asks for the one-time code from the Host
|
|
187
|
+
backend, opens the approval page, waits for the user to approve it, stores the credential, and
|
|
188
|
+
checks once for approved work. On later runs it reuses the saved credential and skips pairing:
|
|
189
|
+
|
|
190
|
+
```sh
|
|
191
|
+
npm start -- --codex-cd "$HOME/Code/my-host-project"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
This guided command is still a one-shot preview: it exits after finding no work or after starting
|
|
195
|
+
one Codex session. It does not yet install itself as a background service. The explicit `pair` and
|
|
196
|
+
`claim-once` commands below remain available for scripts and for testing each block separately.
|
|
197
|
+
|
|
198
|
+
When attached to a terminal, the CLI shows a readable status view with steps, checks, approval
|
|
199
|
+
state, and next actions. When stdout is piped, or when `--json` is supplied, it emits bounded JSON
|
|
200
|
+
events instead so another process can consume it:
|
|
201
|
+
|
|
202
|
+
```sh
|
|
203
|
+
npm start -- --json --codex-cd "$HOME/Code/my-host-project"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Pair this Mac with a Host user
|
|
207
|
+
|
|
208
|
+
Pairing connects one local Connector to one already-authenticated Host user. It is separate from
|
|
209
|
+
the Host organization's API key and does not give the Connector permission to create Grants or
|
|
210
|
+
send Host events.
|
|
211
|
+
|
|
212
|
+
The flow is:
|
|
213
|
+
|
|
214
|
+
```text
|
|
215
|
+
Host backend -> Receiver: start pairing for its Host-user reference
|
|
216
|
+
Receiver -> Host backend: one-time user code + verification URL
|
|
217
|
+
Connector -> Receiver: claim the code
|
|
218
|
+
Connector -> browser: open the verification URL
|
|
219
|
+
user -> Receiver page: click Approve
|
|
220
|
+
Connector -> Receiver: poll until approved
|
|
221
|
+
Receiver -> Connector: one Connector credential
|
|
222
|
+
Connector -> local disk: save the credential with mode 0600
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The Host backend starts pairing with its organization credential. In the current local preview:
|
|
226
|
+
|
|
227
|
+
```sh
|
|
228
|
+
curl -s -X POST http://127.0.0.1:43218/v0.1/pairing-sessions \
|
|
229
|
+
-H 'Authorization: Bearer host-preview-api-key' \
|
|
230
|
+
-H 'Content-Type: application/json' \
|
|
231
|
+
--data '{"host_subject_ref":"host_user_001"}'
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Run the Connector and enter the returned `user_code` when it asks for it. The code is not placed
|
|
235
|
+
in shell history:
|
|
236
|
+
|
|
237
|
+
```sh
|
|
238
|
+
npm start -- pair \
|
|
239
|
+
--receiver http://127.0.0.1:43218 \
|
|
240
|
+
--credential-file "$HOME/.webmcp-connector/credentials.json"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
For a non-interactive script, pass the code explicitly instead:
|
|
244
|
+
|
|
245
|
+
```sh
|
|
246
|
+
npm start -- pair \
|
|
247
|
+
--receiver http://127.0.0.1:43218 \
|
|
248
|
+
--code 'ABCD-EFGH-IJKL-MNOP' \
|
|
249
|
+
--credential-file "$HOME/.webmcp-connector/credentials.json"
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
In an interactive terminal, the Connector shows the verification URL and waits for you to press
|
|
253
|
+
Enter before opening the approval page. If the browser does not open, use the displayed URL
|
|
254
|
+
manually and click **Approve**. The command keeps polling until approval or expiry, then prints
|
|
255
|
+
`connector_paired`. JSON and other non-interactive callers continue without the Enter prompt.
|
|
256
|
+
|
|
257
|
+
The credential file contains the local bearer credential and is protected with filesystem mode
|
|
258
|
+
0600. Do not commit it, copy it into a Host prompt, or put it in a repository. The Connector never
|
|
259
|
+
prints the bearer value. The current preview permits one active pairing for a Host user; a second
|
|
260
|
+
pairing returns `host_subject_already_paired` until the preview state is revoked or reset.
|
|
261
|
+
|
|
262
|
+
## Claim one delivery and start Codex
|
|
263
|
+
|
|
264
|
+
After pairing, run one manual poll:
|
|
265
|
+
|
|
266
|
+
```sh
|
|
267
|
+
npm start -- claim-once \
|
|
268
|
+
--credential-file "$HOME/.webmcp-connector/credentials.json" \
|
|
269
|
+
--codex-cd "$HOME/Code/my-host-project"
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
The command performs this sequence:
|
|
273
|
+
|
|
274
|
+
```text
|
|
275
|
+
read local credential
|
|
276
|
+
-> preflight Node, Codex, and Host directory
|
|
277
|
+
-> ask Receiver for one delivery lease
|
|
278
|
+
-> validate the lease
|
|
279
|
+
-> start `codex exec --cd <Host project> <fixed continuation prompt>`
|
|
280
|
+
-> print the typed activation result
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
The fixed prompt contains the canonical page, workflow, event, state version, and human decision
|
|
284
|
+
boundary. It does not contain the Receiver bearer, lease token, or private process configuration.
|
|
285
|
+
There is no existing-session lookup or thread mapping.
|
|
286
|
+
|
|
287
|
+
The result meanings are:
|
|
288
|
+
|
|
289
|
+
- `connector_idle`: no pending delivery was available;
|
|
290
|
+
- `activation_dispatch_accepted`: the local Codex process exited successfully; and
|
|
291
|
+
- `outcome_unknown` or another typed result: the process failed, timed out, or the activation was
|
|
292
|
+
rejected.
|
|
293
|
+
|
|
294
|
+
`activation_dispatch_accepted` does not prove that Browser access, page-bound WebMCP execution,
|
|
295
|
+
Host-effect verification, or acknowledgement occurred. Browser permission and the Agent-to-Browser
|
|
296
|
+
connection remain separate runtime capabilities. A future production Connector may run this
|
|
297
|
+
operation under a supervisor or scheduler; the current CLI is one-shot.
|
|
298
|
+
|
|
299
|
+
## Troubleshooting
|
|
300
|
+
|
|
301
|
+
| Code | Meaning | Next action |
|
|
302
|
+
|---|---|---|
|
|
303
|
+
| `connector_node_unsupported` | Node is older than 24 | Install/use Node 24 or newer |
|
|
304
|
+
| `connector_codex_not_found` | No default Codex executable was found | Install Codex, add it to `PATH`, or use `--codex-binary` |
|
|
305
|
+
| `connector_codex_binary_not_found` | The configured executable is missing or not executable | Correct the path or remove the override |
|
|
306
|
+
| `connector_codex_unusable` | `codex --version` failed | Open/login/update Codex, then rerun `doctor` |
|
|
307
|
+
| `connector_codex_cd_missing` | The Host directory does not exist | Correct `--codex-cd` |
|
|
308
|
+
| `connector_codex_cd_unusable` | The Host directory is not readable and writable | Fix local permissions |
|
|
309
|
+
| `connector_credentials_missing` | Pairing has not been completed for this credential file | Run `pair` |
|
|
310
|
+
| `connector_pairing_code_missing` | Guided start needs a one-time code | Ask the Host backend for a code, then enter it or pass `--code` |
|
|
311
|
+
| `pairing_code_invalid` | The entered code is not the expected 16-character Host code | Use a code like `ABCD-EFGH-IJKL-MNOP` from the Host backend |
|
|
312
|
+
| `pairing_request_timeout` | Receiver did not answer in time | Check the Receiver origin and network |
|
|
313
|
+
| `pairing_expired` | The one-time pairing window expired | Ask the Host backend for a new code |
|
|
314
|
+
|
|
315
|
+
## Package boundary
|
|
316
|
+
|
|
317
|
+
- `src/codex-discovery.mjs` — Codex lookup, version verification, Node check, and Host-directory check;
|
|
318
|
+
- `src/pairing-client.mjs` — one-time pairing claim, browser open, and poll;
|
|
319
|
+
- `src/credentials.mjs` — atomic local credential file with restrictive permissions;
|
|
320
|
+
- `src/local-connector.mjs` — one claim and typed adapter dispatch;
|
|
321
|
+
- `src/codex-exec-adapter.mjs` — the fresh-session Codex adapter inside the Connector process;
|
|
322
|
+
- `src/terminal-ui.mjs` — the dependency-free human terminal presentation; and
|
|
323
|
+
- `src/main.mjs` — the small CLI process, guided `start`, and `doctor` command.
|
|
324
|
+
|
|
325
|
+
Run package checks with:
|
|
326
|
+
|
|
327
|
+
```sh
|
|
328
|
+
npm run check:syntax
|
|
329
|
+
npm run test:codex
|
|
330
|
+
npm test
|
|
331
|
+
npm run verify
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
The reusable delivery protocol remains in `reentry-core/`; this package consumes it rather than
|
|
335
|
+
forking Receiver or delivery semantics.
|
|
336
|
+
|
|
337
|
+
</details>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Re-entry Core
|
|
2
|
+
|
|
3
|
+
**Status:** v0.1 protocol, Host SDK, Receiver C1, Receiver Grant control, Connector delivery C2,
|
|
4
|
+
transport/process C3d, Agent Adapter contract C4b, private managed-context resolution C4c,
|
|
5
|
+
source-repository conformance profile C6b, and app-independent quality and weight baseline locally
|
|
6
|
+
verified
|
|
7
|
+
**Authority:** ADR-0006 through ADR-0014 and `Docs/Development/RECORE-001-foundation.md` through
|
|
8
|
+
`Docs/Development/RECORE-006-private-managed-context-binding.md`
|
|
9
|
+
|
|
10
|
+
This directory is the authoritative source for new application-neutral Re-entry Core behavior.
|
|
11
|
+
MVP1 and MVP2 remain unchanged references.
|
|
12
|
+
|
|
13
|
+
## Current surface
|
|
14
|
+
|
|
15
|
+
- `src/protocol.mjs` — strict bounded Manifest, event envelope, public binding, private receipt,
|
|
16
|
+
canonical JSON, Ed25519 signing, and typed errors.
|
|
17
|
+
- `src/host-sdk.mjs` — narrow Host-side Manifest and event issuance without Receiver or Agent
|
|
18
|
+
authority.
|
|
19
|
+
- `src/receiver-core.mjs` — Receiver-owned consent challenge, private Grant, public binding,
|
|
20
|
+
authenticated same-subject inspection and atomic revocation, exact event replay, atomic
|
|
21
|
+
pending-delivery reservation, and a narrow delivery facade behind injected authority ports.
|
|
22
|
+
- `src/receiver-delivery.mjs` — internal target-scoped claim, short lease, bounded-attempt,
|
|
23
|
+
stale-worker fencing, and Host-effect-backed acknowledgement state machine.
|
|
24
|
+
- `src/receiver-support.mjs` — shared strict Receiver validation, immutable-value, and typed-error
|
|
25
|
+
helpers.
|
|
26
|
+
- `src/sqlite-receiver-store.mjs` — optional Node SQLite reference store with explicit
|
|
27
|
+
transactions, additive schema migration, WAL and full synchronous durability for file-backed
|
|
28
|
+
state, and no fallback.
|
|
29
|
+
- `src/sqlite-receiver-schema.mjs` — internal versioned schema and delivery projection.
|
|
30
|
+
- `src/cloud-receiver-http.mjs` — strict bounded Host-event, delivery-claim, and effect-
|
|
31
|
+
acknowledgement HTTP mapping over an injected Receiver Core.
|
|
32
|
+
- `src/local-connector-client.mjs` — outbound-only no-retry Connector client with secure-origin,
|
|
33
|
+
timeout, response-size, redirect, and exact-response validation.
|
|
34
|
+
- `src/agent-adapter.mjs` — credential-free lease-to-activation derivation, one-call bounded
|
|
35
|
+
adapter dispatch, and explicit accepted, unsupported, rejected, or unknown outcomes.
|
|
36
|
+
- `src/managed-context-adapter.mjs` — private Grant-to-context resolution through one configured
|
|
37
|
+
adapter authority and one selected driver, with no raw context locator in typed activation or
|
|
38
|
+
result surfaces.
|
|
39
|
+
- `src/receiver-http-contract.mjs` — internal route, field, and transport-limit constants.
|
|
40
|
+
- `conformance/` — source-repository-only domain-neutral Host, Receiver, Connector, deterministic
|
|
41
|
+
Agent, and redacted orchestration profile; excluded from runtime exports and package files.
|
|
42
|
+
- `bench/` — bounded protocol, durable Receiver, Agent Adapter, and source-profile local regression
|
|
43
|
+
entrypoints; excluded from runtime exports and package files.
|
|
44
|
+
- `test/` — positive, negative, tamper, boundary, privacy, rollback, restart, and independent-
|
|
45
|
+
process tests; fault wrappers remain test-only.
|
|
46
|
+
- `protocol/test-vectors/` — frozen interoperability inputs and outputs.
|
|
47
|
+
|
|
48
|
+
## Commands
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm run verify
|
|
52
|
+
npm test
|
|
53
|
+
npm run test:conformance
|
|
54
|
+
npm run benchmark:protocol
|
|
55
|
+
npm run benchmark:agent-adapter
|
|
56
|
+
npm run benchmark:receiver
|
|
57
|
+
npm run benchmark:profile
|
|
58
|
+
node --test test/receiver-core.test.mjs test/sqlite-receiver-store.test.mjs
|
|
59
|
+
node --test test/separate-process.test.mjs
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
From a source checkout, run the non-production conformance profile with:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
node conformance/run.mjs
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The package has zero runtime dependencies and targets Node 24 or newer.
|
|
69
|
+
`npm run verify` is the source-checkout closure command: it checks JavaScript syntax, runs the full
|
|
70
|
+
test suite, executes the direct conformance profile, and inspects the dry-run package surface.
|
|
71
|
+
The repository `.node-version` selects the reproducible Node 24 closure runtime; runs on newer local
|
|
72
|
+
runtimes are additional compatibility evidence and must name the executed version.
|
|
73
|
+
`SqliteReceiverStore` is available only through the `./sqlite-receiver-store` subpath, so the
|
|
74
|
+
root, protocol, Host SDK, and Receiver Core imports do not load `node:sqlite` implicitly.
|
|
75
|
+
|
|
76
|
+
Local verification covers strict shapes, canonical encoding, Ed25519 signing and verification,
|
|
77
|
+
trusted-origin anchoring, tamper and boundary rejection, frozen vectors, Host SDK isolation,
|
|
78
|
+
trusted consent integration, private-output boundaries, atomic run reservation, exact replay,
|
|
79
|
+
authenticated Grant inspection, revocation-before-event and event-before-revocation ordering,
|
|
80
|
+
idempotent revocation replay, target and subject isolation, replayable lease claims, bounded
|
|
81
|
+
reclamation, stale-worker fencing, pre-revocation effect convergence, post-revocation effect
|
|
82
|
+
rejection, transaction rollback, token non-persistence, version-1 migration, and file
|
|
83
|
+
close-and-reopen persistence. Focused transport tests also cover ordinary JSON request mapping,
|
|
84
|
+
no-work responses, bounds, redacted failures, origin policy, redirects, timeouts, malformed or
|
|
85
|
+
stale responses, and absence of automatic retry. The source-repository conformance profile runs
|
|
86
|
+
Host, Receiver, and Connector children independently, exercises one deterministic Agent dispatch,
|
|
87
|
+
rejects acknowledgement before a separate synthetic Host effect, emits one redacted result, and
|
|
88
|
+
cleans its exact temporary files. The forced-restart test reuses those role implementations and
|
|
89
|
+
adds test-only response-loss injection. Both remain local evidence only.
|
|
90
|
+
Deterministic Agent Adapter tests cover credential omission, expiry and correlation rejection,
|
|
91
|
+
all bounded outcomes and unavailable capabilities, one-call behavior, timeout, exception,
|
|
92
|
+
malformed result, immutability, and the no-effect/no-acknowledgement boundary.
|
|
93
|
+
Managed-context adapter tests cover private `grant_id` lookup, exact adapter scoping, active,
|
|
94
|
+
missing, expired, lease-shorter, late-resolution, mismatched, malformed, accessor, exception,
|
|
95
|
+
timeout, and raw-reference non-disclosure behavior. The deterministic authority and driver do not
|
|
96
|
+
prove capture, persistence, or real context activation.
|
|
97
|
+
|
|
98
|
+
The Receiver benchmark uses file-backed SQLite with WAL and full synchronous durability. The
|
|
99
|
+
profile benchmark cold-spawns the unchanged source conformance runner. Both emit bounded JSON and,
|
|
100
|
+
like the protocol and Agent Adapter measurements, are local regression baselines rather than
|
|
101
|
+
throughput promises, production latency, cross-machine comparisons, or service SLAs.
|
|
102
|
+
|
|
103
|
+
## Current non-claims
|
|
104
|
+
|
|
105
|
+
This kernel does not implement a production consent, Grant-control, or pairing session; a consent
|
|
106
|
+
or administration UI; a Grant-control HTTP route; a TLS listener or public Cloud Receiver service;
|
|
107
|
+
a production Connector daemon; durable Connector credential or claim-token storage; a real Host-
|
|
108
|
+
effect verifier; Agent activation; Browser acquisition; WebMCP runtime access; deployment; or a
|
|
109
|
+
selected Host application. Test child processes are evidence scaffolding, not shipping services.
|
|
110
|
+
The conformance profile uses synthetic authorities and is not a production service shell. The
|
|
111
|
+
deterministic adapter is contract evidence, not a runtime fallback or a real Agent. Unsupported
|
|
112
|
+
capability is not replaced by a hidden fallback.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webmcp-challenge/reentry-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Lightweight domain-neutral contracts for governed WebMCP re-entry.",
|
|
7
|
+
"files": [
|
|
8
|
+
"src/",
|
|
9
|
+
"protocol/test-vectors/"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./src/index.mjs",
|
|
13
|
+
"./protocol": "./src/protocol.mjs",
|
|
14
|
+
"./host-sdk": "./src/host-sdk.mjs",
|
|
15
|
+
"./receiver-core": "./src/receiver-core.mjs",
|
|
16
|
+
"./cloud-receiver-http": "./src/cloud-receiver-http.mjs",
|
|
17
|
+
"./local-connector-client": "./src/local-connector-client.mjs",
|
|
18
|
+
"./receiver-http-contract": "./src/receiver-http-contract.mjs",
|
|
19
|
+
"./agent-adapter": "./src/agent-adapter.mjs",
|
|
20
|
+
"./managed-context-adapter": "./src/managed-context-adapter.mjs",
|
|
21
|
+
"./sqlite-receiver-store": "./src/sqlite-receiver-store.mjs"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"check:syntax": "node scripts/check-syntax.mjs",
|
|
25
|
+
"test": "node --test test/*.test.mjs",
|
|
26
|
+
"test:conformance": "node --test test/protocol.test.mjs",
|
|
27
|
+
"verify:conformance": "node conformance/run.mjs",
|
|
28
|
+
"verify:package": "node scripts/verify-package.mjs",
|
|
29
|
+
"verify": "npm run check:syntax && npm test && npm run verify:conformance && npm run verify:package",
|
|
30
|
+
"benchmark:protocol": "node bench/protocol.mjs",
|
|
31
|
+
"benchmark:agent-adapter": "node bench/agent-adapter.mjs",
|
|
32
|
+
"benchmark:receiver": "node bench/receiver-lifecycle.mjs",
|
|
33
|
+
"benchmark:profile": "node bench/profile-startup.mjs"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=24"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"protocol_version": "0.1",
|
|
3
|
+
"issuer_origin": "https://host.example",
|
|
4
|
+
"key_id": "host_vector_001",
|
|
5
|
+
"public_key_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAexPFz3rVIm1COdpt2RVq3NBtTM9ycspPEAAVqC3VZlA=\n-----END PUBLIC KEY-----\n",
|
|
6
|
+
"verification_time": "2026-08-31T03:05:00.000Z",
|
|
7
|
+
"manifest": {
|
|
8
|
+
"type": "webmcp.reentry_manifest",
|
|
9
|
+
"protocol_version": "0.1",
|
|
10
|
+
"manifest_id": "manifest_vector_001",
|
|
11
|
+
"correlation_id": "correlation_vector_001",
|
|
12
|
+
"issuer_origin": "https://host.example",
|
|
13
|
+
"issued_at": "2026-08-31T03:00:00.000Z",
|
|
14
|
+
"offer_expires_at": "2026-08-31T03:10:00.000Z",
|
|
15
|
+
"workflow": {
|
|
16
|
+
"id": "workflow_vector_001",
|
|
17
|
+
"type": "domain-neutral-workflow",
|
|
18
|
+
"state_version": 7,
|
|
19
|
+
"canonical_url": "https://host.example/workflows/workflow_vector_001"
|
|
20
|
+
},
|
|
21
|
+
"display": {
|
|
22
|
+
"title": "Continue this workflow",
|
|
23
|
+
"reason": "The authoritative Host state changed while the Agent was away."
|
|
24
|
+
},
|
|
25
|
+
"grant_request": {
|
|
26
|
+
"event_type": "workflow.ready",
|
|
27
|
+
"grant_expires_at": "2026-08-31T04:00:00.000Z",
|
|
28
|
+
"max_runs": 1,
|
|
29
|
+
"human_boundary": "explicit_receiver_consent"
|
|
30
|
+
},
|
|
31
|
+
"signature": {
|
|
32
|
+
"algorithm": "Ed25519",
|
|
33
|
+
"key_id": "host_vector_001",
|
|
34
|
+
"value": "GJlwB_hB_o1X-Jk5u7jtAhooFQkQ5F4EWLOnrzPAdxpnjVfP1URSb642Pt2yuCyGjiIZ9ePjgC79kGGXttjrCQ"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"manifest_canonical_json": "{\"correlation_id\":\"correlation_vector_001\",\"display\":{\"reason\":\"The authoritative Host state changed while the Agent was away.\",\"title\":\"Continue this workflow\"},\"grant_request\":{\"event_type\":\"workflow.ready\",\"grant_expires_at\":\"2026-08-31T04:00:00.000Z\",\"human_boundary\":\"explicit_receiver_consent\",\"max_runs\":1},\"issued_at\":\"2026-08-31T03:00:00.000Z\",\"issuer_origin\":\"https://host.example\",\"manifest_id\":\"manifest_vector_001\",\"offer_expires_at\":\"2026-08-31T03:10:00.000Z\",\"protocol_version\":\"0.1\",\"signature\":{\"algorithm\":\"Ed25519\",\"key_id\":\"host_vector_001\",\"value\":\"GJlwB_hB_o1X-Jk5u7jtAhooFQkQ5F4EWLOnrzPAdxpnjVfP1URSb642Pt2yuCyGjiIZ9ePjgC79kGGXttjrCQ\"},\"type\":\"webmcp.reentry_manifest\",\"workflow\":{\"canonical_url\":\"https://host.example/workflows/workflow_vector_001\",\"id\":\"workflow_vector_001\",\"state_version\":7,\"type\":\"domain-neutral-workflow\"}}",
|
|
38
|
+
"event_envelope": {
|
|
39
|
+
"body": "{\"binding_id\":\"binding_vector_001\",\"canonical_url\":\"https://host.example/workflows/workflow_vector_001\",\"correlation_id\":\"correlation_vector_001\",\"event_id\":\"event_vector_001\",\"event_sequence\":1,\"event_type\":\"workflow.ready\",\"issuer_origin\":\"https://host.example\",\"occurred_at\":\"2026-08-31T03:04:00.000Z\",\"protocol_version\":\"0.1\",\"state_version\":8,\"type\":\"webmcp.continuation_event\",\"workflow_id\":\"workflow_vector_001\"}",
|
|
40
|
+
"headers": {
|
|
41
|
+
"WebMCP-Reentry-Key-Id": "host_vector_001",
|
|
42
|
+
"WebMCP-Reentry-Timestamp": "1788145440",
|
|
43
|
+
"WebMCP-Reentry-Signature": "3Nm3tu0kQJ63HRJy1bq0fMIz7zibO5z01A2wRdUawC7Vu9iY3RM6cUEWmIRfMARX7n6sA5KaXEtk7GadGjHgAA"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"event_canonical_json": "{\"binding_id\":\"binding_vector_001\",\"canonical_url\":\"https://host.example/workflows/workflow_vector_001\",\"correlation_id\":\"correlation_vector_001\",\"event_id\":\"event_vector_001\",\"event_sequence\":1,\"event_type\":\"workflow.ready\",\"issuer_origin\":\"https://host.example\",\"occurred_at\":\"2026-08-31T03:04:00.000Z\",\"protocol_version\":\"0.1\",\"state_version\":8,\"type\":\"webmcp.continuation_event\",\"workflow_id\":\"workflow_vector_001\"}"
|
|
47
|
+
}
|