@wacando/agent 0.0.0-stage → 2.0.0-rc.1
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/.agents/plugins/marketplace.json +10 -0
- package/.claude-plugin/marketplace.json +12 -0
- package/.cursor-plugin/marketplace.json +12 -0
- package/README.md +166 -2
- package/STATUS.md +121 -0
- package/THIRD-PARTY-NOTICES.txt +1928 -0
- package/adapters/README.md +12 -0
- package/adapters/claude/mcp.mjs +7 -0
- package/adapters/codex/mcp.mjs +7 -0
- package/adapters/cursor/mcp.mjs +7 -0
- package/bin/wacando-agent.mjs +243 -0
- package/docs/AGENT_TOOLS.md +129 -0
- package/docs/CURSOR_IDENTITY_RESUME.md +579 -0
- package/docs/MCP-AUDIT.md +355 -0
- package/docs/MCP-CONTRACT.md +138 -0
- package/docs/MIGRATION-2.0.md +36 -0
- package/docs/OMEMO_PREKEY_INTEGRATION.md +125 -0
- package/docs/ONBOARDING-VALIDATION.md +88 -0
- package/docs/ONBOARDING.md +212 -0
- package/docs/ONBOARDING_PLUGIN_CONTRACT.md +156 -0
- package/docs/PLUGIN_HANDOFF_FOLLOWUP.md +178 -0
- package/docs/PUBLIC_ONBOARDING_READINESS.md +156 -0
- package/docs/RELEASE.md +25 -0
- package/docs/WACANDO_PACKAGES.md +26 -0
- package/docs/evidence/issue-2/DOCUMENTARY_FOLLOWUP.md +107 -0
- package/docs/evidence/issue-2/QUALIFICATION_LINK_FOLLOWUP.md +105 -0
- package/docs/evidence/issue-2/REVIEW_FOLLOWUP.md +93 -0
- package/docs/evidence/issue-2/baseline.txt +76 -0
- package/docs/evidence/issue-2/check-mcp.txt +14 -0
- package/docs/evidence/issue-2/check.txt +376 -0
- package/docs/evidence/issue-2/codex-exec-help.json +11 -0
- package/docs/evidence/issue-2/codex-help.json +10 -0
- package/docs/evidence/issue-2/cursor-help.json +10 -0
- package/docs/evidence/issue-2/documentary-check.txt +376 -0
- package/docs/evidence/issue-2/documentary-validation.txt +7 -0
- package/docs/evidence/issue-2/local-build-api.txt +203 -0
- package/docs/evidence/issue-2/local-build-first.txt +87 -0
- package/docs/evidence/issue-2/local-build-policy-first.txt +34 -0
- package/docs/evidence/issue-2/local-build-policy.txt +153 -0
- package/docs/evidence/issue-2/local-build-web.txt +219 -0
- package/docs/evidence/issue-2/local-check-mcp.txt +14 -0
- package/docs/evidence/issue-2/local-check.txt +376 -0
- package/docs/evidence/issue-2/local-codex-probe.txt +3 -0
- package/docs/evidence/issue-2/local-codex-probe2.txt +3 -0
- package/docs/evidence/issue-2/local-codex.txt +2 -0
- package/docs/evidence/issue-2/local-cursor-probe.txt +1 -0
- package/docs/evidence/issue-2/local-cursor.txt +2 -0
- package/docs/evidence/issue-2/local-down.txt +32 -0
- package/docs/evidence/issue-2/local-health.txt +1 -0
- package/docs/evidence/issue-2/local-live.txt +28 -0
- package/docs/evidence/issue-2/local-seed.txt +26 -0
- package/docs/evidence/issue-2/local-status.txt +6 -0
- package/docs/evidence/issue-2/local-up.txt +18 -0
- package/docs/evidence/issue-2/prepare-local-stack.py +67 -0
- package/docs/evidence/issue-2/qualification-body-validation.txt +9 -0
- package/docs/evidence/issue-2/qualification-link-check.txt +376 -0
- package/docs/evidence/issue-2/qualification-link-validation.txt +20 -0
- package/docs/evidence/issue-2/review-check.txt +376 -0
- package/docs/evidence/issue-2/review-validation.txt +218 -0
- package/docs/evidence/issue-7/README.md +21 -0
- package/docs/evidence/issue-7/check-mcp.txt +9 -0
- package/docs/evidence/issue-7/check.txt +381 -0
- package/docs/evidence/issue-7/live.txt +23 -0
- package/docs/evidence/issue-8/README.md +56 -0
- package/docs/evidence/issue-8/check-mcp.txt +9 -0
- package/docs/evidence/issue-8/check.txt +465 -0
- package/docs/evidence/issue-8/e2e-desktop-observer-human-devices.txt +30 -0
- package/docs/evidence/issue-8/e2e-desktop-observer-main-without-109.txt +17 -0
- package/docs/evidence/issue-8/e2e-desktop-observer.txt +26 -0
- package/docs/evidence/issue-8/live-regression-human-devices.txt +24 -0
- package/docs/evidence/issue-8/live-regression.txt +23 -0
- package/docs/evidence/issue-8/review-fixes/README.md +30 -0
- package/docs/evidence/issue-8/review-fixes/check-mcp.txt +9 -0
- package/docs/evidence/issue-8/review-fixes/check.txt +484 -0
- package/docs/evidence/issue-8/review-fixes/e2e-desktop-observer.txt +28 -0
- package/docs/evidence/issue-8/review-fixes/onboarding-live.txt +15 -0
- package/docs/evidence/issue-8/review-fixes/session-replacement-live.txt +13 -0
- package/docs/evidence/npm-release/check-mcp.txt +9 -0
- package/docs/evidence/npm-release/check.txt +484 -0
- package/docs/evidence/npm-release/e2e-desktop-observer.txt +28 -0
- package/package.json +66 -4
- package/packages/core/limits.mjs +24 -0
- package/packages/core/store.mjs +92 -0
- package/packages/core/validation.mjs +25 -0
- package/packages/mcp/agent-tools.mjs +82 -0
- package/packages/mcp/server.mjs +161 -0
- package/packages/mcp/stdio.mjs +42 -0
- package/packages/onboarding/network.mjs +60 -0
- package/packages/onboarding/service.mjs +235 -0
- package/packages/onboarding/storage.mjs +99 -0
- package/packages/onboarding/version.mjs +2 -0
- package/packages/runtime/conversations.mjs +384 -0
- package/packages/runtime/device.mjs +34 -0
- package/packages/runtime/index.mjs +8 -0
- package/packages/runtime/pairing.mjs +110 -0
- package/packages/runtime/runtime.mjs +213 -0
- package/packages/runtime/session.mjs +52 -0
- package/packages/server/cli.mjs +18 -0
- package/packages/server/server.mjs +110 -0
- package/packages/server/stream.mjs +42 -0
- package/packages/web/app.js +85 -0
- package/packages/web/history.js +48 -0
- package/packages/web/index.html +17 -0
- package/packages/web/style.css +1 -0
- package/plugins/wacando/.codex-plugin/plugin.json +18 -0
- package/plugins/wacando/.mcp.json +8 -0
- package/plugins/wacando/skills/wacando/SKILL.md +33 -0
- package/plugins/wacando-claude/.claude-plugin/plugin.json +10 -0
- package/plugins/wacando-claude/.mcp.json +8 -0
- package/plugins/wacando-claude/README.md +88 -0
- package/plugins/wacando-claude/skills/open/SKILL.md +66 -0
- package/plugins/wacando-cursor/.cursor-plugin/plugin.json +11 -0
- package/plugins/wacando-cursor/README.md +48 -0
- package/plugins/wacando-cursor/commands/wacando-open.md +10 -0
- package/plugins/wacando-cursor/mcp.json +8 -0
- package/plugins/wacando-cursor/skills/wacando/SKILL.md +50 -0
- package/provenance.json +503 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# MCP implementation audit
|
|
2
|
+
|
|
3
|
+
Date: September 22, 2026. Baseline: `60e06c39dac8bf7dcad4e08cd804a70591ce5915`.
|
|
4
|
+
Environment: Node.js `v22.22.0`, Linux. Official MCP Inspector: `2.7.0`.
|
|
5
|
+
|
|
6
|
+
## Remediation status
|
|
7
|
+
|
|
8
|
+
All seven findings below have been corrected in the shared sources and regenerated
|
|
9
|
+
in the Codex, Cursor and Claude plugin runtimes. The original observations are
|
|
10
|
+
preserved below as baseline evidence; their line numbers refer to the audited
|
|
11
|
+
commit, not the current files. The [MCP contract](MCP-CONTRACT.md) describes the
|
|
12
|
+
resulting behavior, limits, and supported revision.
|
|
13
|
+
|
|
14
|
+
| Finding | Correction | Regression coverage |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| F1 | Invalid HTTP request targets return 400; unexpected handler failures are contained | [HTTP survival and retained-event test](../tests/http-hardening.test.mjs) |
|
|
17
|
+
| F2 | Validate request IDs/envelopes and method parameters; ignore responses and notifications without replying | [Protocol negative tests](../tests/mcp-protocol.test.mjs) |
|
|
18
|
+
| F3 | Share tool schemas and strict validation, reject extra/provider arguments, count Unicode code points consistently | [Schema and Unicode tests](../tests/mcp-protocol.test.mjs) |
|
|
19
|
+
| F4 | Bound input/output frames, rates, store bytes, pages, connections and SSE queues; await output writes | [Protocol/resource tests](../tests/mcp-protocol.test.mjs), [HTTP/SSE tests](../tests/http-hardening.test.mjs), [viewer history tests](../tests/viewer-history.test.mjs) |
|
|
20
|
+
| F5 | Complete handshakes in test clients and enforce initialization state in the server | [Protocol tests](../tests/mcp-protocol.test.mjs), [relocated plugin tests](../tests/plugins.test.mjs) |
|
|
21
|
+
| F6 | HTTP sockets have a shutdown grace period; MCP also has a final exit deadline for unread stdout pipes | [HTTP shutdown tests](../tests/http-hardening.test.mjs), [stalled stdout test](../tests/mcp-protocol.test.mjs) |
|
|
22
|
+
| F7 | Build into clean staging directories, preserve old runtimes on preparation failure, compare exact generated inventories and bytes | [Build regression](../tests/build.test.mjs), [generated-file check](../scripts/check-generated.mjs) |
|
|
23
|
+
|
|
24
|
+
`open_viewer` now reports a visibility preference and an unknown browser state.
|
|
25
|
+
All host skills identify recorded text as untrusted historical data and explain
|
|
26
|
+
pagination, rate-limit retries, and the 8 MiB retention budget. The viewer merges
|
|
27
|
+
live events with paginated history without duplicates or resurrecting evictions.
|
|
28
|
+
|
|
29
|
+
The supported protocol remains `2024-11-05`, explicitly documented and tested.
|
|
30
|
+
Migration to the modern revision and optional structured results are versioned
|
|
31
|
+
feature work, not unresolved defects in this legacy contract. Runtime dependencies
|
|
32
|
+
remain empty, and existing host installations have not been overwritten.
|
|
33
|
+
|
|
34
|
+
Remediation verification: `npm run check` passes all **29 tests** and the exact
|
|
35
|
+
runtime inventory/content checks. `npm run check:mcp` passes official Inspector
|
|
36
|
+
tool discovery and synthetic recording for all three generated adapters. Native
|
|
37
|
+
host browser behavior and Windows/macOS remain outside this verification.
|
|
38
|
+
|
|
39
|
+
## Initial assessment (baseline)
|
|
40
|
+
|
|
41
|
+
The server interoperates with the official Inspector through the legacy MCP
|
|
42
|
+
protocol, but it is not ready for a blanket claim of protocol compliance or
|
|
43
|
+
robustness. A malformed local HTTP request terminates the MCP process. JSON-RPC
|
|
44
|
+
envelopes and tool inputs are insufficiently validated, resource limits are
|
|
45
|
+
incomplete, and the automated tests do not exercise a complete MCP handshake.
|
|
46
|
+
|
|
47
|
+
The initial audit changed documentation only. Its probes used disposable processes
|
|
48
|
+
and synthetic fixtures, not real user conversations or installed host instances.
|
|
49
|
+
The subsequent fixes are summarized in the remediation table above.
|
|
50
|
+
|
|
51
|
+
## Scope and authoritative references
|
|
52
|
+
|
|
53
|
+
Reviewed the shared MCP server, event store, HTTP/SSE viewer service, browser-side
|
|
54
|
+
data handling, all three adapters, plugin manifests and MCP configurations,
|
|
55
|
+
skills and browser instructions, package generation, installers, and tests.
|
|
56
|
+
|
|
57
|
+
The protocol reference is **https://modelcontextprotocol.io**, using explicit
|
|
58
|
+
revision URLs. The implementation announces `2024-11-05`; that revision is the
|
|
59
|
+
baseline for its existing wire contract. The current official documentation also
|
|
60
|
+
describes `2026-07-28`, which has substantially different discovery and versioning.
|
|
61
|
+
|
|
62
|
+
The local HTTP service is a **viewer API**, not an MCP HTTP transport. Its SSE
|
|
63
|
+
events are application events. Missing MCP HTTP headers, OAuth discovery, an MCP
|
|
64
|
+
POST endpoint, or MCP HTTP session management are therefore not findings here.
|
|
65
|
+
The authorization specification distinguishes stdio from HTTP authorization.
|
|
66
|
+
See [MCP authorization](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization).
|
|
67
|
+
|
|
68
|
+
The official protocol does not make using an SDK a prerequisite for conformance.
|
|
69
|
+
The repository's zero-runtime-dependency constraint can be preserved, but the
|
|
70
|
+
manual transport needs stronger validation and independent interoperability tests.
|
|
71
|
+
|
|
72
|
+
## Findings
|
|
73
|
+
|
|
74
|
+
### F1 — High: malformed viewer URLs terminate the MCP process
|
|
75
|
+
|
|
76
|
+
Location: [HTTP handler](../packages/server/server.mjs), line 28.
|
|
77
|
+
|
|
78
|
+
`new URL(req.url, origin)` is outside the handler's exception boundary. Sending
|
|
79
|
+
`GET //[ HTTP/1.1` with the correct local Host header causes `ERR_INVALID_URL`.
|
|
80
|
+
Because the asynchronous HTTP callback rejects without a handler, Node exits.
|
|
81
|
+
|
|
82
|
+
Reproduced against a disposable Codex MCP process after valid initialization:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
HTTP client: ECONNRESET
|
|
86
|
+
Server: TypeError: Invalid URL
|
|
87
|
+
Location: packages/server/server.mjs:28:22
|
|
88
|
+
Process exit: 1
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The viewer and MCP share this process, so the failure disconnects the host and
|
|
92
|
+
discards its entire in-memory store. All packaged adapters share the affected
|
|
93
|
+
code. The demonstrated attack surface is local HTTP access with an accepted Host;
|
|
94
|
+
this is not evidence of a remote cross-origin exploit.
|
|
95
|
+
|
|
96
|
+
Correction: catch malformed request-target parsing and return HTTP 400. Contain
|
|
97
|
+
unexpected handler failures without terminating the process, and add a regression
|
|
98
|
+
test that confirms MCP calls and previously recorded events survive the request.
|
|
99
|
+
This is a service robustness defect, not a missing MCP HTTP feature.
|
|
100
|
+
|
|
101
|
+
### F2 — Medium: invalid JSON-RPC envelopes produce invalid successful replies
|
|
102
|
+
|
|
103
|
+
Location: [MCP dispatch](../packages/mcp/server.mjs), lines 29–37.
|
|
104
|
+
|
|
105
|
+
Only `jsonrpc` and `method` are checked. Requests with IDs `null`, `true`, `{}`,
|
|
106
|
+
`[]`, or `1.5` receive successful `ping` results echoing those IDs. Scalar
|
|
107
|
+
`params`, such as `"invalid"`, are also accepted. A response-shaped input is
|
|
108
|
+
misclassified as a request and receives an error response.
|
|
109
|
+
|
|
110
|
+
For example:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{"jsonrpc":"2.0","id":true,"method":"ping"}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Observed reply:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{"jsonrpc":"2.0","id":true,"result":{}}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
MCP specifies string or integer request IDs, forbids null request IDs, and
|
|
123
|
+
distinguishes requests, responses, and notifications.
|
|
124
|
+
See [MCP messages](https://modelcontextprotocol.io/specification/2024-11-05/basic/messages).
|
|
125
|
+
|
|
126
|
+
Correction: validate the envelope before dispatch; classify message kinds;
|
|
127
|
+
reject malformed requests without echoing invalid IDs into success responses;
|
|
128
|
+
validate method parameters; and avoid replying to valid notifications or
|
|
129
|
+
unsolicited responses. Add malformed-message tests alongside valid string and
|
|
130
|
+
integer ID cases. Error responses to unidentifiable malformed input should be
|
|
131
|
+
treated separately from successful responses to valid MCP requests.
|
|
132
|
+
|
|
133
|
+
### F3 — Medium: tool implementations do not enforce their advertised schemas
|
|
134
|
+
|
|
135
|
+
Locations: [tool schemas and dispatch](../packages/mcp/server.mjs), lines 7–20
|
|
136
|
+
and 39–45; [event validation](../packages/core/store.mjs), lines 14–25.
|
|
137
|
+
|
|
138
|
+
Reproduced after calling the server:
|
|
139
|
+
|
|
140
|
+
| Input | Observed behavior | Advertised contract |
|
|
141
|
+
| --- | --- | --- |
|
|
142
|
+
| Valid `record_event` fields plus `unexpected: true` | Event recorded | Additional properties forbidden |
|
|
143
|
+
| `record_event` with `type: null` | Recorded as `message` | Type must be an enumerated string |
|
|
144
|
+
| `open_viewer` with `arguments: 42` | Success | Arguments must be an object |
|
|
145
|
+
| `get_events` with an unsupported conversation filter | Entire snapshot returned | No arguments accepted |
|
|
146
|
+
|
|
147
|
+
The store enforces nonblank required strings and length limits, but those limits
|
|
148
|
+
are absent from the published input schema. The packaging test even sends a
|
|
149
|
+
`provider` argument that the schema forbids, then expects success.
|
|
150
|
+
|
|
151
|
+
MCP requires validation of tool inputs.
|
|
152
|
+
See [tool security requirements](https://modelcontextprotocol.io/specification/2024-11-05/server/tools#security-considerations).
|
|
153
|
+
|
|
154
|
+
Correction: enforce object shape, allowed properties, types, enum values, and
|
|
155
|
+
length constraints at the tool boundary. Keep store validation as a second
|
|
156
|
+
layer. Publish the actual constraints and test schema/implementation agreement,
|
|
157
|
+
including Unicode length semantics. Reject a client-supplied provider while
|
|
158
|
+
continuing to assign provider identity from the adapter.
|
|
159
|
+
|
|
160
|
+
Distinguish malformed `tools/call` envelopes from domain validation failures.
|
|
161
|
+
Do not mechanically replace every `isError: true` with a JSON-RPC error: the
|
|
162
|
+
official guidance explicitly allows tool-level input validation errors.
|
|
163
|
+
See [tool error handling](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#error-handling).
|
|
164
|
+
|
|
165
|
+
### F4 — Medium: framing, invocation rates, and result sizes need bounds
|
|
166
|
+
|
|
167
|
+
Locations: [stdio input/output](../packages/mcp/server.mjs), lines 22–25;
|
|
168
|
+
[get_events](../packages/mcp/server.mjs), line 42;
|
|
169
|
+
[HTTP snapshots and streams](../packages/server/server.mjs), lines 30–51.
|
|
170
|
+
|
|
171
|
+
There is no application-level invocation rate limit, no maximum incoming stdio
|
|
172
|
+
line size, and no handling of stdout backpressure. `readline` can accumulate an
|
|
173
|
+
arbitrarily long unfinished line before store validation is reached. A probe
|
|
174
|
+
sent a one-megabyte unused argument to `open_viewer` and received success.
|
|
175
|
+
|
|
176
|
+
`get_events` always returns the full store. With 1,000 valid events of 32,000
|
|
177
|
+
ASCII characters each, serialization through the current result shape produced
|
|
178
|
+
**32,274,017 bytes**. HTTP snapshots and SSE reconnection also copy the full
|
|
179
|
+
history. Bounded event count does not provide a small response or bounded
|
|
180
|
+
transport queues. This can overwhelm host tool-result/context limits and cause
|
|
181
|
+
large memory spikes. Actual out-of-memory failure was not induced.
|
|
182
|
+
|
|
183
|
+
MCP's tool security section explicitly requires rate limiting.
|
|
184
|
+
See [tool security requirements](https://modelcontextprotocol.io/specification/2024-11-05/server/tools#security-considerations).
|
|
185
|
+
The particular byte budgets below are implementation recommendations, not
|
|
186
|
+
protocol-prescribed constants.
|
|
187
|
+
|
|
188
|
+
Correction: bound input bytes before newline parsing, rate-limit calls, handle
|
|
189
|
+
stdout backpressure with bounded queues, and cap response bytes. Give
|
|
190
|
+
`get_events` a bounded page size and conversation/sequence selection with a
|
|
191
|
+
continuation mechanism. Review SSE client limits, initial snapshots, and slow
|
|
192
|
+
readers under the same memory budget. This is pagination of a tool's data;
|
|
193
|
+
pagination of the three-item `tools/list` is not required to fix it.
|
|
194
|
+
|
|
195
|
+
### F5 — Medium: current tests give incomplete lifecycle assurance
|
|
196
|
+
|
|
197
|
+
Locations: [runtime MCP test](../tests/runtime.test.mjs), lines 52–72;
|
|
198
|
+
[plugin tests](../tests/plugins.test.mjs), lines 31–56;
|
|
199
|
+
[MCP test helper](../tests/helpers/mcp-client.mjs);
|
|
200
|
+
[MCP lifecycle handling](../packages/mcp/server.mjs), lines 32–38.
|
|
201
|
+
|
|
202
|
+
The runtime test sends `initialize` without the required parameters. Plugin
|
|
203
|
+
tests do not send `notifications/initialized` or validate the negotiated
|
|
204
|
+
protocol version. The store-isolation test invokes tools without initialization.
|
|
205
|
+
The server accepts all these sequences and ignores every notification. A direct
|
|
206
|
+
probe successfully recorded an event before initialization and successfully
|
|
207
|
+
initialized with an empty object.
|
|
208
|
+
|
|
209
|
+
For the announced legacy revision, initialization precedes normal operation,
|
|
210
|
+
and the client sends the initialized notification after negotiation.
|
|
211
|
+
See [legacy lifecycle](https://modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle).
|
|
212
|
+
|
|
213
|
+
Correction: make test clients perform a complete handshake, check a supported
|
|
214
|
+
negotiated version, and cover invalid initialization, notifications, framing,
|
|
215
|
+
error replies, and shutdown. Define server handling of premature calls and
|
|
216
|
+
repeated initialization explicitly. Treat pre-initialization rejection as
|
|
217
|
+
defensive hardening; the legacy specification's client sequencing obligations
|
|
218
|
+
do not themselves mandate a particular server rejection code.
|
|
219
|
+
|
|
220
|
+
The official Inspector checks below improve confidence for normal clients, but
|
|
221
|
+
they do not replace negative tests or establish complete conformance.
|
|
222
|
+
|
|
223
|
+
### F6 — Medium: shutdown has no application-controlled deadline
|
|
224
|
+
|
|
225
|
+
Locations: [MCP stop handler](../packages/mcp/server.mjs), lines 50–54;
|
|
226
|
+
[HTTP close](../packages/server/server.mjs), lines 62–66.
|
|
227
|
+
|
|
228
|
+
An accepted TCP socket with unfinished HTTP headers can keep `server.close()`
|
|
229
|
+
pending. The code tracks SSE responses but not all sockets, and has no deadline
|
|
230
|
+
for finishing shutdown. Once stopping begins, the stop guard also makes a
|
|
231
|
+
subsequent SIGTERM ineffective at advancing shutdown.
|
|
232
|
+
|
|
233
|
+
A disposable-process probe opened a socket, sent `GET / HTTP/1.1\r\n`, and closed
|
|
234
|
+
MCP stdin. The process was still running after 1.5 seconds and after another
|
|
235
|
+
second following SIGTERM. Closing the HTTP socket allowed a clean exit. This
|
|
236
|
+
demonstrates a peer-dependent shutdown delay; the probe did not wait for Node's
|
|
237
|
+
HTTP timeout and does not assert that the delay is infinite.
|
|
238
|
+
|
|
239
|
+
Correction: stop accepting work, finish active responses, then destroy remaining
|
|
240
|
+
connections after a short grace period. Test EOF and SIGTERM with an active SSE
|
|
241
|
+
stream and incomplete HTTP requests. Legacy MCP discusses shutdown timeouts,
|
|
242
|
+
and current stdio guidance recommends prompt exit on EOF.
|
|
243
|
+
See [legacy lifecycle](https://modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle)
|
|
244
|
+
and [current stdio shutdown](https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio#shutdown).
|
|
245
|
+
|
|
246
|
+
### F7 — Low: package builds retain deleted source files
|
|
247
|
+
|
|
248
|
+
Location: [package builder](../scripts/build.mjs), lines 7–11.
|
|
249
|
+
|
|
250
|
+
The build copies source trees into existing runtime directories without removing
|
|
251
|
+
obsolete files. In an isolated copy of the repository, a synthetic source file
|
|
252
|
+
was built, deleted from source, and built again. All three plugin runtimes still
|
|
253
|
+
contained it. This can retain retired code or assets in distributed packages.
|
|
254
|
+
No obsolete sensitive file was found in the current packages.
|
|
255
|
+
|
|
256
|
+
Correction: generate each runtime into a clean staging directory and replace
|
|
257
|
+
only the build-owned output, then check exact source/output inventories. In CI,
|
|
258
|
+
verify that rebuilding does not leave uncommitted runtime changes. This is a
|
|
259
|
+
packaging defect, not a protocol violation.
|
|
260
|
+
|
|
261
|
+
## Compatibility and secondary recommendations
|
|
262
|
+
|
|
263
|
+
- **Legacy-only support is a limitation, not automatically a negotiation bug.**
|
|
264
|
+
Always returning `2024-11-05` is allowed if that is the only supported legacy
|
|
265
|
+
revision. The Inspector successfully accepts that fallback. A newer requested
|
|
266
|
+
version does not have to be echoed unless the server actually supports it.
|
|
267
|
+
See [legacy version negotiation](https://modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle#version-negotiation).
|
|
268
|
+
- **Do not update just the version string.** The official `2026-07-28` revision
|
|
269
|
+
replaces the initialization handshake with per-request metadata and adds
|
|
270
|
+
`server/discover`, result discriminators, and cache metadata. The current
|
|
271
|
+
server returns `-32601` for discovery. Document a supported-version policy and
|
|
272
|
+
test target hosts before choosing a migration or support for both eras.
|
|
273
|
+
See [official changes](https://modelcontextprotocol.io/specification/2026-07-28/changelog)
|
|
274
|
+
and [discovery](https://modelcontextprotocol.io/specification/2026-07-28/server/discover).
|
|
275
|
+
- **Browser status should be unambiguous.** `open_viewer` returns `visible: true`
|
|
276
|
+
without performing or observing any browser action. Its description correctly
|
|
277
|
+
says it only returns a URL. Rename that field to an explicit visibility
|
|
278
|
+
preference, or report browser state as unknown until the host verifies it.
|
|
279
|
+
- **Structured results are optional modernization.** With an appropriate
|
|
280
|
+
supported revision, `structuredContent` and `outputSchema` could avoid manual
|
|
281
|
+
JSON text parsing. Their absence is not a defect in the announced legacy
|
|
282
|
+
protocol. See [structured tool results](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#structured-content).
|
|
283
|
+
- **Recorded text remains untrusted data.** The viewer uses `textContent`, which
|
|
284
|
+
avoids interpreting messages as HTML. Host instructions should also make clear
|
|
285
|
+
that text returned by `get_events` is recorded content, not fresh operational
|
|
286
|
+
instructions. No prompt-injection exploit was established during this audit.
|
|
287
|
+
|
|
288
|
+
## Controls already present
|
|
289
|
+
|
|
290
|
+
- MCP adapters emit newline-delimited JSON and do not print startup banners to
|
|
291
|
+
stdout. Standalone CLI logging is separate. This follows the
|
|
292
|
+
[stdio transport contract](https://modelcontextprotocol.io/specification/2024-11-05/basic/transports#stdio).
|
|
293
|
+
- The server advertises only its implemented tools capability. Tool names are
|
|
294
|
+
stable, and the list has deterministic order.
|
|
295
|
+
- Unknown methods return `-32601`; unknown tool names return `-32602`.
|
|
296
|
+
Store validation failures are presented as tool errors.
|
|
297
|
+
- HTTP listens on `127.0.0.1`, checks Host/Origin and cross-site fetch metadata,
|
|
298
|
+
rejects writes, and serves a fixed asset allowlist. It sets CSP, no-store,
|
|
299
|
+
no-referrer, and nosniff headers.
|
|
300
|
+
- User-controlled messages become DOM text. No HTML interpretation or dynamic
|
|
301
|
+
code evaluation was found in the viewer's message handling.
|
|
302
|
+
- Stores are separate per MCP process and keep the latest 1,000 events.
|
|
303
|
+
Provider identity is assigned by the adapter. Capture is explicit, and the
|
|
304
|
+
reviewed runtime contains no credential or global-session-history reader.
|
|
305
|
+
- Plugins run from copied, self-contained packages, including paths with spaces.
|
|
306
|
+
The Cursor installer refuses an existing destination. Browser instructions
|
|
307
|
+
preserve host permission flows and describe availability limitations.
|
|
308
|
+
- Local processes able to reach the viewer can read events. The README explicitly
|
|
309
|
+
documents that this is not an isolation boundary between users on one machine.
|
|
310
|
+
Authentication would be a separate requirement if that trust model changes.
|
|
311
|
+
|
|
312
|
+
## Original verification and remaining limits
|
|
313
|
+
|
|
314
|
+
`npm run check` passed: all three runtimes rebuilt, and **9/9 tests** passed.
|
|
315
|
+
The rebuild left tracked runtime files unchanged.
|
|
316
|
+
|
|
317
|
+
The following commands used the official Inspector. All exited successfully:
|
|
318
|
+
|
|
319
|
+
```sh
|
|
320
|
+
npx --yes @modelcontextprotocol/inspector@2.7.0 --cli node adapters/codex/mcp.mjs --method tools/list
|
|
321
|
+
npx --yes @modelcontextprotocol/inspector@2.7.0 --cli node plugins/wacando/runtime/adapters/codex/mcp.mjs --method initialize
|
|
322
|
+
npx --yes @modelcontextprotocol/inspector@2.7.0 --cli node plugins/wacando-cursor/runtime/adapters/cursor/mcp.mjs --method initialize
|
|
323
|
+
npx --yes @modelcontextprotocol/inspector@2.7.0 --cli node plugins/wacando-claude/runtime/adapters/claude/mcp.mjs --method tools/call --tool-name record_event --tool-arg conversationId=audit-synthetic --tool-arg agentId=audit-probe --tool-arg 'text=Synthetic audit fixture; not a real agent message.'
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
These are the documented [Inspector CLI](https://modelcontextprotocol.io/docs/2026-07-28/tools/inspector/cli)
|
|
327
|
+
workflow, pinned for reproducibility. Each command creates its own short-lived
|
|
328
|
+
server; the returned viewer URL is not a persistent preview. Inspector was not
|
|
329
|
+
added as a runtime dependency. An npm warning concerned Inspector's own legacy
|
|
330
|
+
transport dependency, not a dependency of Wacando.
|
|
331
|
+
|
|
332
|
+
Additional direct Node probes established F1–F3, the oversized input and result
|
|
333
|
+
measurements in F4, premature calls in F5, the shutdown delay in F6, and stale
|
|
334
|
+
build output in F7. Large Unicode events were also delivered in an SSE probe;
|
|
335
|
+
no claim of reproducible SSE message loss is made.
|
|
336
|
+
|
|
337
|
+
No host was reinstalled, no host browser was opened, and no marketplace was
|
|
338
|
+
modified. Current Codex/Cursor/Claude UI loading, native browser behavior,
|
|
339
|
+
Windows/macOS behavior, and remote/container port access were not verified.
|
|
340
|
+
The earlier host observations in [STATUS.md](../STATUS.md) remain historical
|
|
341
|
+
evidence, not fresh end-to-end validation. Stress exhaustion and an exhaustive
|
|
342
|
+
protocol conformance suite were outside this audit.
|
|
343
|
+
|
|
344
|
+
## Original recommended order
|
|
345
|
+
|
|
346
|
+
1. Fix F1 and add its process-survival regression test.
|
|
347
|
+
2. Fix F2–F3 and repair the lifecycle test client in F5.
|
|
348
|
+
3. Bound transport/resource usage and shutdown in F4/F6.
|
|
349
|
+
4. Make generated packages exact in F7 and clarify browser result semantics.
|
|
350
|
+
5. Choose and document the supported MCP revision set, then add a pinned
|
|
351
|
+
Inspector interoperability check for each packaged adapter.
|
|
352
|
+
|
|
353
|
+
Implement fixes in shared sources, run `npm run check`, and regenerate all three
|
|
354
|
+
plugin runtimes through the builder. Existing host installations require their
|
|
355
|
+
normal update flow; changing this checkout alone does not update them.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# MCP contract and verification
|
|
2
|
+
|
|
3
|
+
The authoritative protocol reference is [modelcontextprotocol.io](https://modelcontextprotocol.io).
|
|
4
|
+
Protocol changes must identify the supported revision and update interoperability
|
|
5
|
+
and negative tests. Do not infer requirements for the viewer API from the MCP HTTP
|
|
6
|
+
transport specification.
|
|
7
|
+
|
|
8
|
+
## Supported revision and lifecycle
|
|
9
|
+
|
|
10
|
+
Wacando implements **MCP `2024-11-05` over stdio**, with the `tools` capability.
|
|
11
|
+
It supports `open_viewer`, `record_event`, `get_events`,
|
|
12
|
+
`wacando_verify_installation`, and `wacando_enroll_agent`.
|
|
13
|
+
The viewer needs no credentials. Onboarding manages protected local credentials
|
|
14
|
+
and bundled messaging components; see [onboarding v1](ONBOARDING.md).
|
|
15
|
+
No prompts, resources, sampling, server-initiated requests or task execution
|
|
16
|
+
capabilities are advertised.
|
|
17
|
+
|
|
18
|
+
The client sends valid `initialize` parameters, accepts the returned revision,
|
|
19
|
+
then sends `notifications/initialized`. Only then are tools available. Ping is
|
|
20
|
+
allowed during initialization. Invalid initialization does not advance state;
|
|
21
|
+
repeated initialization is rejected. Unknown methods return `-32601`, including
|
|
22
|
+
the modern `server/discover` probe, so clients supporting both eras can fall back
|
|
23
|
+
to the legacy handshake. A newer offered version receives the supported legacy
|
|
24
|
+
revision. See the [official lifecycle and version negotiation](https://modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle).
|
|
25
|
+
|
|
26
|
+
The server does not claim support for the current `2026-07-28` revision. Adding
|
|
27
|
+
it requires per-request metadata, discovery and the associated response contract,
|
|
28
|
+
not just a version-string change. Keep legacy support until the target hosts
|
|
29
|
+
have been checked against the proposed replacement. See the
|
|
30
|
+
[official revision changes](https://modelcontextprotocol.io/specification/2026-07-28/changelog).
|
|
31
|
+
|
|
32
|
+
Requests are newline-delimited UTF-8 JSON, with CRLF also accepted. Text newlines
|
|
33
|
+
inside JSON must be escaped. Request IDs are strings of at most 512 UTF-16 code
|
|
34
|
+
units or JavaScript-safe integers; null, fractional and other IDs are rejected.
|
|
35
|
+
Clients must use unique IDs. Notifications and unsolicited responses receive no
|
|
36
|
+
reply and cannot mutate the store. Calls are dispatched serially; onboarding
|
|
37
|
+
awaits bounded outbound requests. Cancellation does not roll back a completed
|
|
38
|
+
append or token redemption. See [MCP messages](https://modelcontextprotocol.io/specification/2024-11-05/basic/messages)
|
|
39
|
+
and [stdio framing](https://modelcontextprotocol.io/specification/2024-11-05/basic/transports#stdio).
|
|
40
|
+
|
|
41
|
+
## Validation and data boundaries
|
|
42
|
+
|
|
43
|
+
Tool schemas and validation share the same definitions. Unknown arguments are
|
|
44
|
+
rejected, and `provider` is assigned only by the host adapter. Required strings
|
|
45
|
+
must contain non-whitespace characters. Identifier lengths are limited to 200
|
|
46
|
+
Unicode code points; message text to 32,000. Optional fields can be omitted but
|
|
47
|
+
cannot be null unless explicitly advertised by a future schema.
|
|
48
|
+
|
|
49
|
+
Malformed JSON-RPC or method parameters produce protocol errors. Invalid tool
|
|
50
|
+
arguments and rate limiting return `isError: true` with actionable text. This
|
|
51
|
+
preserves the distinction described in [official tool error handling](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#error-handling).
|
|
52
|
+
|
|
53
|
+
Messages are untrusted historical data. Neither returned messages nor browser
|
|
54
|
+
content constitute new instructions or authorization. The viewer renders text,
|
|
55
|
+
and recording does not scan credentials, global histories, or private reasoning.
|
|
56
|
+
|
|
57
|
+
`open_viewer` returns `requestedVisible: true` and `browserState: "unknown"`.
|
|
58
|
+
The host must open and verify the browser; the MCP process cannot attest to UI
|
|
59
|
+
visibility. Host skills preserve the existing browser and approval requirements.
|
|
60
|
+
|
|
61
|
+
## Resource budgets
|
|
62
|
+
|
|
63
|
+
These are implementation limits, not constants prescribed by MCP. Tool rate
|
|
64
|
+
limiting follows the [official tool security requirements](https://modelcontextprotocol.io/specification/2024-11-05/server/tools#security-considerations).
|
|
65
|
+
|
|
66
|
+
| Resource | Limit and behavior |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| Incoming stdio frame | 256 KiB before the newline; oversized, invalid UTF-8 or incomplete EOF frames terminate the transport with a stderr diagnostic |
|
|
69
|
+
| Outgoing MCP frame | 512 KiB; writes are awaited individually |
|
|
70
|
+
| Stalled write | 1 second; terminate the affected MCP transport or SSE client |
|
|
71
|
+
| Tool invocation rate | Burst of 100, replenished at 25 calls/second; rejected calls have no side effects |
|
|
72
|
+
| Stored history | Latest 1,000 events or 8 MiB of serialized event bytes, whichever is reached first |
|
|
73
|
+
| Event data page | At most 256 KiB; default 50 events, maximum 100 |
|
|
74
|
+
| HTTP request rate | Burst of 100, replenished at 50 requests/second, per process; excess requests receive 429 |
|
|
75
|
+
| HTTP connections | At most 32 simultaneous connections, including incomplete requests |
|
|
76
|
+
| SSE clients | At most 8; excess streams receive 503 |
|
|
77
|
+
| SSE output queue | 512 KiB per client, including the active write; close a client that exceeds it |
|
|
78
|
+
| HTTP shutdown grace | 250 ms; remaining sockets are destroyed after the grace period |
|
|
79
|
+
| MCP shutdown deadline | Allow protected onboarding cleanup (including an in-flight call/retry) to finish, bounded by 45 seconds with exit 1 on timeout; then allow 1 second for an unread stdout pipe before forcing exit |
|
|
80
|
+
|
|
81
|
+
The byte cap describes serialized data, not total process heap usage. Live stream
|
|
82
|
+
consumers are individually bounded; a slow viewer does not queue unlimited data
|
|
83
|
+
or interrupt other viewers. Host processes and browsers should reconnect after a
|
|
84
|
+
transport failure. Normal stdin EOF and SIGTERM close the viewer, including active
|
|
85
|
+
streams and incomplete HTTP requests.
|
|
86
|
+
|
|
87
|
+
## Reading events
|
|
88
|
+
|
|
89
|
+
`get_events` and `GET /api/events` accept:
|
|
90
|
+
|
|
91
|
+
- `conversationId`: optional exact conversation filter.
|
|
92
|
+
- `afterSequence`: exclusive cursor, default zero.
|
|
93
|
+
- `throughSequence`: inclusive upper bound, default the current sequence.
|
|
94
|
+
- `limit`: maximum events, from 1 to 100, default 50.
|
|
95
|
+
|
|
96
|
+
Each response includes `events`, `sequence`, `oldestSequence`, `retention`,
|
|
97
|
+
`byteLimit`, `retainedBytes`, `historyTruncated`, and `nextAfterSequence`.
|
|
98
|
+
Keep the first page's `sequence` as `throughSequence` and follow
|
|
99
|
+
`nextAfterSequence` until it is null. A page may be shorter than `limit` because
|
|
100
|
+
of its byte budget. An unknown conversation produces an empty page. Evicted
|
|
101
|
+
history cannot be recovered; `historyTruncated` indicates the requested cursor
|
|
102
|
+
predates retained history, independently of the conversation filter.
|
|
103
|
+
|
|
104
|
+
Example tool arguments:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{"conversationId":"task-1","afterSequence":50,"throughSequence":120,"limit":50}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
SSE sends a bounded `snapshot` page first. The viewer fetches remaining history
|
|
111
|
+
over paginated HTTP while live `message` events continue. Each live payload is
|
|
112
|
+
`{event, oldestSequence}`. The viewer merges by ID, sorts by sequence, respects
|
|
113
|
+
eviction, and ignores history responses from superseded connections. Export is
|
|
114
|
+
disabled while the snapshot is incomplete. This SSE format belongs to the viewer
|
|
115
|
+
application, not the MCP transport.
|
|
116
|
+
|
|
117
|
+
## Builds and checks
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
npm run check
|
|
121
|
+
npm run check:mcp
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`check` regenerates runtimes from clean staging directories, compares every
|
|
125
|
+
generated file against its source, and runs the regression suite. Preparation
|
|
126
|
+
failures preserve the previous runtime. Only build-owned runtime directories are
|
|
127
|
+
replaced; plugin manifests, skills and existing host installations are preserved.
|
|
128
|
+
|
|
129
|
+
`check:mcp` runs the official Inspector pinned to `2.7.0` against each generated
|
|
130
|
+
adapter, checking discovery through `tools/list` and a synthetic recording. It
|
|
131
|
+
uses npm's executable cache and may need network access on its first run. The
|
|
132
|
+
Inspector is development verification tooling, not a runtime dependency. See the
|
|
133
|
+
[official Inspector CLI](https://modelcontextprotocol.io/docs/2026-07-28/tools/inspector/cli).
|
|
134
|
+
|
|
135
|
+
For CI, run both commands and `git diff --exit-code -- plugins/*/runtime` to ensure
|
|
136
|
+
the checked-in packages match regenerated output. Commit runtime changes alongside
|
|
137
|
+
their shared sources. Host installation and native-browser tests are separate;
|
|
138
|
+
a successful CLI check does not verify a host's browser UI.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Migrating to runtime 2.0 (official libsignal OMEMO)
|
|
2
|
+
|
|
3
|
+
Runtime/plugin 1.x encrypted with the **classic** OMEMO backend
|
|
4
|
+
(`@privacyresearch/libsignal-protocol-typescript`, GPL-3.0, no PQXDH). The
|
|
5
|
+
Wacando desktop apps use only the official `@signalapp/libsignal-client` and
|
|
6
|
+
cannot decrypt classic sessions. Runtime 2.0 ships **only** the official
|
|
7
|
+
backend (`@wacando/omemo`): bundles carry Kyber prekeys and sessions
|
|
8
|
+
use PQXDH.
|
|
9
|
+
|
|
10
|
+
There is no in-place key conversion: an identity key is bound to its device,
|
|
11
|
+
its published bundle and its peers' trust pins.
|
|
12
|
+
|
|
13
|
+
## What happens to an existing 1.x identity
|
|
14
|
+
|
|
15
|
+
On connect, the runtime finds `classic-state.json` in the identity's protected
|
|
16
|
+
state directory and stops with:
|
|
17
|
+
|
|
18
|
+
> This identity was created by plugin 1.x with the retired classic OMEMO format
|
|
19
|
+
> ... revoke it on the site and pair a new identity with a different address
|
|
20
|
+
|
|
21
|
+
Nothing is deleted, rewritten or published: the classic keys stay on disk, no
|
|
22
|
+
native device is created next to them, and no plaintext path exists.
|
|
23
|
+
|
|
24
|
+
## Re-enrollment
|
|
25
|
+
|
|
26
|
+
1. Stop every host or daemon using the old identity.
|
|
27
|
+
2. In the Wacando app, revoke the old agent.
|
|
28
|
+
3. Pair a new identity (new address) with this runtime: `wacando-agent pair
|
|
29
|
+
<code>` or the `wacando_pair` MCP tool ([pairing](AGENT_TOOLS.md)). The runtime generates a new
|
|
30
|
+
native device locally.
|
|
31
|
+
4. Optionally archive, then delete, the old protected state directory once you
|
|
32
|
+
no longer need it (`~/.wacando-plugin/<partition>/omemo-<digest>/`). The
|
|
33
|
+
runtime never does this for you.
|
|
34
|
+
|
|
35
|
+
Conversations of the old identity are not migrated; observers keep their own
|
|
36
|
+
history.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# OMEMO prekey integration — September 23, 2026
|
|
2
|
+
|
|
3
|
+
The upstream corrections described in
|
|
4
|
+
`/home/kyle/work/wacando/docs/OMEMO_PREKEY_REVIEW.md` are now incorporated into
|
|
5
|
+
this plugin checkout. The shared messaging bundle, preserved upstream sources,
|
|
6
|
+
provenance and all three generated runtimes were regenerated. No backend or API
|
|
7
|
+
contract changes, publication, deployment or push were performed here.
|
|
8
|
+
|
|
9
|
+
## Included corrections and provenance
|
|
10
|
+
|
|
11
|
+
- Publication replenishes the backend that owns the advertised prekeys; the
|
|
12
|
+
classic bridge cannot shadow them with different private material.
|
|
13
|
+
- Classic consumption removes and persists the canonical native prekey.
|
|
14
|
+
- Session initiation selects a sender-specific slot.
|
|
15
|
+
- Replenishment allocates monotonically increasing, persisted prekey IDs.
|
|
16
|
+
|
|
17
|
+
The upstream revision recorded in provenance is
|
|
18
|
+
`babaa329fe288aa56cfb5e6b6b3c89a2d9aad86c`. The upstream fixes were uncommitted:
|
|
19
|
+
that revision alone does **not** identify the imported code. All 154 input hashes
|
|
20
|
+
in `packages/onboarding/vendor/provenance.json` were checked against the upstream
|
|
21
|
+
working tree. Bundle and provenance copies match in all three runtimes.
|
|
22
|
+
|
|
23
|
+
SHA-256 of `packages/onboarding/vendor/messaging.cjs`:
|
|
24
|
+
`f316806787afce10d6df0a499a2e6b2b2ed5899fb47898b9e31024dffe08e5b3`.
|
|
25
|
+
|
|
26
|
+
Existing identity keys, signed prekeys and ratchet state are preserved. There is
|
|
27
|
+
no automatic identity reset or plaintext fallback. Restart the MCP host to load
|
|
28
|
+
an updated installed package; keep its existing protected state directory.
|
|
29
|
+
The installer refuses to overwrite an existing installation, so stage the new
|
|
30
|
+
package separately and update the host registration using the
|
|
31
|
+
[installation guide](ONBOARDING.md).
|
|
32
|
+
|
|
33
|
+
## Independently repeated in the actual plugin checkout
|
|
34
|
+
|
|
35
|
+
Environment: Linux, Node.js 22.22.0, npm 10.9.4, local service
|
|
36
|
+
`http://localhost:3005`, actual ejabberd and a sandboxed headless system Chrome
|
|
37
|
+
observer. The fixtures create synthetic accounts and revoke their test agents.
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
node scripts/vendor-messaging.mjs /home/kyle/work/wacando
|
|
41
|
+
npm run check
|
|
42
|
+
npm run check:mcp
|
|
43
|
+
WACANDO_LIVE_TEST_ORIGIN=http://localhost:3005 node --test tests/onboarding-live.test.mjs
|
|
44
|
+
|
|
45
|
+
WACANDO_CHECKOUT=/home/kyle/work/wacando \
|
|
46
|
+
/home/kyle/work/wacando/apps/adapter/node_modules/.bin/tsx \
|
|
47
|
+
scripts/check-crypto-interop.mts --after-publication --two-senders
|
|
48
|
+
|
|
49
|
+
WACANDO_CHECKOUT=/home/kyle/work/wacando \
|
|
50
|
+
WACANDO_LIVE_TEST_ORIGIN=http://localhost:3005 \
|
|
51
|
+
WACANDO_CHROMIUM_EXECUTABLE=/usr/bin/google-chrome \
|
|
52
|
+
/home/kyle/work/wacando/apps/adapter/node_modules/.bin/tsx \
|
|
53
|
+
scripts/check-encrypted-interop.mts
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
| Check | Result |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| Build and exact generated-runtime verification | PASS, all three runtimes |
|
|
59
|
+
| `npm run check` final run | 43 PASS, three opt-in live tests skipped |
|
|
60
|
+
| Official MCP Inspector 2.7.0 | PASS, all three runtimes |
|
|
61
|
+
| Explicit live onboarding suite | 3/3 PASS: verification, enrollment, OMEMO, restart and revocation |
|
|
62
|
+
| Offline crypto regression | 4/4 PASS: both directions and two observer senders after publication preparation |
|
|
63
|
+
| Packaged plugin → native adapter and real browser | PASS |
|
|
64
|
+
| Native adapter → plugin and real browser | PASS |
|
|
65
|
+
| Injected heartbeat outage and recovery | PASS, one XMPP connection and one grant; subsequent encrypted traffic received |
|
|
66
|
+
| Browser STOP | PASS, subsequent encrypted plugin stanza rejected by ejabberd |
|
|
67
|
+
| Server canary scans | PASS, zero occurrences for all three prefixes in fresh dumps, logs and spool |
|
|
68
|
+
| `git diff --check` | PASS |
|
|
69
|
+
|
|
70
|
+
The first `npm run check`, overlapping the crypto/network checks, had five
|
|
71
|
+
deadline failures: three MCP request timeouts and two relocated-package test
|
|
72
|
+
timeouts (38 passed, three failed, two cancelled, three skipped). An unchanged
|
|
73
|
+
rerun passed all 43 tests in 10.5 seconds. No timeout threshold or product code
|
|
74
|
+
was changed to obtain the passing run. Scheduling contention is a possible
|
|
75
|
+
explanation, not a proven root cause; these failures do not explain the earlier
|
|
76
|
+
transient enrollment failure recorded in the baseline.
|
|
77
|
+
|
|
78
|
+
Server scans were repeated from `/home/kyle/work/wacando` for each of
|
|
79
|
+
`SYNTHETIC_PLUGIN_`, `SYNTHETIC_ADAPTER_`, `SYNTHETIC_AFTER_HEARTBEAT_`:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
EJABBERD_CONTAINER=wacando-preview-xmpp \
|
|
83
|
+
bash packages/omemo/scripts/canary-scan.sh SYNTHETIC_PLUGIN_
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The upstream 49/49 OMEMO unit-test result is reported in its review; it was not
|
|
87
|
+
rerun here. The plugin regression and full encrypted network path above were
|
|
88
|
+
rerun against this checkout's regenerated bundle. The older failing results in
|
|
89
|
+
[the handoff follow-up](PLUGIN_HANDOFF_FOLLOWUP.md) are historical evidence.
|
|
90
|
+
|
|
91
|
+
## Remaining limits and resumption
|
|
92
|
+
|
|
93
|
+
- A cached bundle can still select an already consumed prekey, including a
|
|
94
|
+
collision between devices belonging to one sender. Such a session is rejected.
|
|
95
|
+
Automatic bundle refresh and complete recovery of old broken sessions are not
|
|
96
|
+
implemented. Do not delete identity files or claim that lost private prekeys
|
|
97
|
+
can be reconstructed. The successful two-sender run does not prove that all
|
|
98
|
+
possible slot collisions are avoided.
|
|
99
|
+
- Production onboarding's reported 404 remains unresolved. HTTPS/WSS production
|
|
100
|
+
onboarding was not qualified by these local checks.
|
|
101
|
+
- Actual Codex CLI 0.153.4 tool invocation and literal site prompts were repeated
|
|
102
|
+
against the final bundle after this vendor refresh: verification, enrollment
|
|
103
|
+
and fresh-host resume all passed using `WACANDO_LIVE_TEST_ORIGIN=http://localhost:3005
|
|
104
|
+
WACANDO_CHECKOUT=/home/kyle/work/wacando node scripts/check-host-onboarding.mjs`.
|
|
105
|
+
No durable credential markers appeared in host output. Runtime tests cover all three MCP
|
|
106
|
+
runtimes. Cursor Agent CLI 2026.08.25-3e8eec8 subsequently passed verification,
|
|
107
|
+
enrollment and fresh-host resume using the final copied plugin; see the public
|
|
108
|
+
readiness record for the command and scope. Claude and graphical host UIs,
|
|
109
|
+
Codex Desktop installation UI, Windows and long outage campaigns remain to
|
|
110
|
+
be qualified. The browser here is a Playwright-controlled web observer, not
|
|
111
|
+
Codex's in-app browser.
|
|
112
|
+
- The encrypted-message fixture uses the packaged session's internal provider
|
|
113
|
+
and client. It does not add or imply a public messaging MCP tool.
|
|
114
|
+
- Preserve saved credentials and keys when resuming a completed enrollment.
|
|
115
|
+
Reinvoke enrollment with the same origin, installation and identity; do not
|
|
116
|
+
redeem the consumed temporary token again. The separate API limitation when
|
|
117
|
+
enrollment consumes a token but its durable response is lost remains unchanged;
|
|
118
|
+
follow the recovery guide rather than claiming enrollment succeeded.
|
|
119
|
+
- No npm package name availability is asserted. The versioned npx command in
|
|
120
|
+
the installation guide remains a publication placeholder. Nothing was
|
|
121
|
+
published or deployed.
|
|
122
|
+
|
|
123
|
+
The [public onboarding readiness record](PUBLIC_ONBOARDING_READINESS.md) tracks
|
|
124
|
+
deployment preparation, public probes, remaining host work and the proposed
|
|
125
|
+
consumed-prekey recovery design. Initial deadline failures remain unexplained.
|