@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,88 @@
|
|
|
1
|
+
# Onboarding v1 validation — September 23, 2026
|
|
2
|
+
|
|
3
|
+
The [OMEMO integration record](OMEMO_PREKEY_INTEGRATION.md) contains the latest
|
|
4
|
+
checks after incorporating the upstream prekey fixes. The historical
|
|
5
|
+
[handoff review follow-up](PLUGIN_HANDOFF_FOLLOWUP.md) records the connection
|
|
6
|
+
lifetime correction and original crypto failures. The results below are the
|
|
7
|
+
earlier onboarding baseline, not a public-release qualification.
|
|
8
|
+
|
|
9
|
+
Environment: Linux, Node.js 22.22.0, npm 10.9.4, Codex CLI 0.153.4.
|
|
10
|
+
Service under test: `http://localhost:3005`, with the actual local API and
|
|
11
|
+
ejabberd WebSocket service. Only labelled synthetic accounts were created.
|
|
12
|
+
No production availability is asserted. Existing uncommitted repository changes
|
|
13
|
+
were preserved; no backend source/configuration changes, publication or push
|
|
14
|
+
were performed.
|
|
15
|
+
|
|
16
|
+
| Command | Result |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| `npm run check` | 40 passed; 3 opt-in live tests skipped; generated runtimes match shared sources |
|
|
19
|
+
| `npm run check:mcp` | Official Inspector 2.7.0 passed for all three packaged adapters |
|
|
20
|
+
| `WACANDO_LIVE_TEST_ORIGIN=http://localhost:3005 node --test tests/onboarding-live.test.mjs` | 3 passed against real API/XMPP/OMEMO |
|
|
21
|
+
| `WACANDO_LIVE_TEST_ORIGIN=http://localhost:3005 node scripts/check-host-onboarding.mjs` | Actual Codex host invoked installed verification and enrollment tools; another fresh host resumed enrollment without redemption |
|
|
22
|
+
| `python3 /home/kyle/.codex/skills/.system/plugin-creator/scripts/validate_plugin.py plugins/wacando` | Passed |
|
|
23
|
+
| `git diff --check` | Passed |
|
|
24
|
+
| Local `npm pack` followed by `npm exec --yes --package=<local-tarball> -- wacando-plugin --version` | Returned `1.0.0`; 142 packaged files, approximately 1.09 MB compressed; nothing published |
|
|
25
|
+
|
|
26
|
+
The packaging test runs `npm pack`, inspects the resulting tarball, extracts it
|
|
27
|
+
outside the checkout, invokes its version command, and installs all three host
|
|
28
|
+
packages into isolated destinations. Reinstallation refuses to overwrite a marker
|
|
29
|
+
representing existing user content. Hidden plugin/MCP/marketplace files are included.
|
|
30
|
+
|
|
31
|
+
Live tests check owner-visible `verifiedAt` and `connectedAt` after actual plugin
|
|
32
|
+
tool calls. They also cover challenge replay through a fresh plugin state,
|
|
33
|
+
wrong installation, invalidation of a replaced token, restart preserving the
|
|
34
|
+
private OMEMO identity, and revocation preventing later connection attempts.
|
|
35
|
+
The plugin's stdout/MCP results and stderr are checked for durable credential
|
|
36
|
+
markers. Owner cookies are confined to the test controller.
|
|
37
|
+
|
|
38
|
+
Unit tests cover challenge/token expiration responses, network response loss,
|
|
39
|
+
failure to persist the durable enrollment response, rejected redirects,
|
|
40
|
+
origin/host/identity isolation, unsafe permissions and symlinks, locking,
|
|
41
|
+
failed OMEMO publication suppressing the callback, and corrupt local keys.
|
|
42
|
+
They simulate expiry errors; the live test does not wait 10/15 minutes or alter
|
|
43
|
+
database timestamps to force real wall-clock expiry.
|
|
44
|
+
|
|
45
|
+
## Precisely what was tested in hosts
|
|
46
|
+
|
|
47
|
+
- **Codex CLI 0.153.4:** real model-driven MCP calls against a copied installed
|
|
48
|
+
plugin runtime registered in that invocation's MCP configuration. Verification,
|
|
49
|
+
enrollment and resume each ran in a fresh ephemeral Codex session. Normal
|
|
50
|
+
automatic approval review (`--approve-for-me`) remained active. This validates
|
|
51
|
+
actual host tool invocation; it does not qualify Codex Desktop marketplace UI,
|
|
52
|
+
native-browser rendering, or visual observation of the onboarding page.
|
|
53
|
+
- **Cursor:** its self-contained runtime, Inspector interoperability and the
|
|
54
|
+
complete local API/XMPP/OMEMO path passed. Cursor's actual GUI tool invocation,
|
|
55
|
+
reload and plugin UI remain to be qualified.
|
|
56
|
+
- **Claude Code:** its self-contained runtime, Inspector interoperability and
|
|
57
|
+
complete local API/XMPP/OMEMO path passed. The actual Claude Code CLI/Desktop
|
|
58
|
+
host and its plugin validator were unavailable here and remain to be qualified.
|
|
59
|
+
|
|
60
|
+
The first ordinary `codex exec` probe refused the MCP mutation because
|
|
61
|
+
noninteractive execution had an effective `never` approval policy. Switching to
|
|
62
|
+
the supported automatic approval review mode allowed all three host calls.
|
|
63
|
+
No bypass flag or disabled sandbox was used.
|
|
64
|
+
|
|
65
|
+
One initial live Codex-runtime connection attempt failed after durable enrollment;
|
|
66
|
+
the tool reported failure and did not claim connection success. All three runtimes
|
|
67
|
+
passed subsequent full live runs. Diagnostics now identify the failing setup step
|
|
68
|
+
without exposing raw network errors or credentials. No root cause was established
|
|
69
|
+
for that initial transient failure.
|
|
70
|
+
|
|
71
|
+
## Remaining qualification and release gates
|
|
72
|
+
|
|
73
|
+
- Production API availability and HTTPS/WSS deployment interoperability have not
|
|
74
|
+
been tested. Use the configurable loopback preview until deployed endpoints
|
|
75
|
+
are confirmed.
|
|
76
|
+
- The bundled OMEMO implementation is Wacando's existing classic X3DH/Double
|
|
77
|
+
Ratchet backend, not its native PQXDH primary backend. Device publication and
|
|
78
|
+
key persistence are real; encrypted conversation interoperability across all
|
|
79
|
+
endpoint backends is outside this onboarding test.
|
|
80
|
+
- POSIX storage protection was tested; macOS host behavior and Windows ACL/native
|
|
81
|
+
host support remain unqualified. Concurrent identity ownership is locked;
|
|
82
|
+
hard-crash stale locks require the documented recovery procedure.
|
|
83
|
+
- No npm name was claimed or availability assumed. The development package stays
|
|
84
|
+
private. Confirm package ownership, upstream dependency redistribution
|
|
85
|
+
obligations/notices and release packaging before publication. Set
|
|
86
|
+
`WACANDO_PLUGIN_INSTALL_COMMAND` only after the actual pinned command works.
|
|
87
|
+
- Synthetic accounts and installation metadata remain on the local test site;
|
|
88
|
+
created agents were revoked and temporary plugin state removed.
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Plugin onboarding v1
|
|
2
|
+
|
|
3
|
+
The source of truth is `lbframe/wacando/docs/ONBOARDING_PLUGIN_CONTRACT.md`.
|
|
4
|
+
[The complete contract snapshot](ONBOARDING_PLUGIN_CONTRACT.md) was copied from
|
|
5
|
+
the local Wacando checkout on September 23, 2026. Its statement that the plugin
|
|
6
|
+
is not implemented describes the upstream document's publication status.
|
|
7
|
+
This repository implements the plugin side; no backend routes were modified.
|
|
8
|
+
The onboarding protocol is integer `1`; the MCP stdio revision remains
|
|
9
|
+
`2024-11-05`. Plugin manifests and readiness reports use version `1.0.0`.
|
|
10
|
+
|
|
11
|
+
## Installation and host reload
|
|
12
|
+
|
|
13
|
+
Node.js 22+ is required. A fresh clone contains self-contained plugin runtimes.
|
|
14
|
+
The viewer still supports `open_viewer`, `record_event`, and `get_events`.
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm run check
|
|
18
|
+
node bin/wacando-plugin.mjs install --host codex
|
|
19
|
+
node bin/wacando-plugin.mjs install --host cursor
|
|
20
|
+
node bin/wacando-plugin.mjs install --host claude
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Run only the command for the chosen host. The installer copies files, refuses
|
|
24
|
+
to overwrite an existing destination, and prints host activation commands.
|
|
25
|
+
Use `--dest /absolute/new/path` to stage an update while preserving an existing
|
|
26
|
+
installation. It does not replace host configuration. If `wacando-local` is
|
|
27
|
+
already registered, use that host's existing marketplace update flow rather
|
|
28
|
+
than registering a conflicting marketplace. Existing repository installation
|
|
29
|
+
commands in the README remain supported.
|
|
30
|
+
|
|
31
|
+
For a site prompt from the local preview, use its `verificationUrl` origin:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
node bin/wacando-plugin.mjs install --host codex --origin http://localhost:3005
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Select `cursor` or `claude` as appropriate. `--origin` validates the destination
|
|
38
|
+
and writes `WACANDO_API_ORIGIN` into the copied package's MCP environment before
|
|
39
|
+
activation. The agent can derive this public origin directly from the prompt;
|
|
40
|
+
the user does not need to edit network configuration or handle any credential.
|
|
41
|
+
Use the actual HTTPS origin for another deployed service. Existing installations
|
|
42
|
+
are never overwritten; stage the updated package and reload its host.
|
|
43
|
+
|
|
44
|
+
- Codex: activate the marketplace/package with the printed commands, reload
|
|
45
|
+
the plugin, then start a new conversation so tool discovery runs again.
|
|
46
|
+
- Cursor: use **Developer: Reload Window**, enable Wacando in **Customize >
|
|
47
|
+
Plugins**, and accept the normal MCP approvals.
|
|
48
|
+
- Claude Code: use the printed marketplace/install commands, then reload
|
|
49
|
+
plugins or restart the host. Desktop and terminal browser behavior is unchanged.
|
|
50
|
+
|
|
51
|
+
The installed server must expose `wacando_verify_installation` and
|
|
52
|
+
`wacando_enroll_agent` in `tools/list`. Never replace verification with curl.
|
|
53
|
+
Do not record onboarding prompts or tokens with the conversation recorder.
|
|
54
|
+
|
|
55
|
+
## Service configuration
|
|
56
|
+
|
|
57
|
+
Production defaults to `https://app.wacando.fr`. For local development set
|
|
58
|
+
`WACANDO_API_ORIGIN=http://localhost:3005` in the MCP server environment and
|
|
59
|
+
reload its host. Origins must match exactly, including ports. A different
|
|
60
|
+
production deployment likewise requires configuring its exact HTTPS origin.
|
|
61
|
+
No user cookie, JID, private key or durable credential is supplied by the user.
|
|
62
|
+
The temporary challenge/token belongs in the site-generated prompt.
|
|
63
|
+
|
|
64
|
+
HTTP and WS are accepted only for loopback development with an explicitly
|
|
65
|
+
configured HTTP origin. URL credentials, query strings, fragments and API
|
|
66
|
+
redirects are rejected. XMPP destinations come from the authenticated enrollment
|
|
67
|
+
response and must use WSS, or loopback WS in this development mode. The bundled
|
|
68
|
+
WebSocket client does not follow redirects. All onboarding traffic is outbound;
|
|
69
|
+
the pre-existing viewer remains bound to loopback and requires no incoming
|
|
70
|
+
Internet port, router mapping, or public listener.
|
|
71
|
+
|
|
72
|
+
## Persistence and recovery
|
|
73
|
+
|
|
74
|
+
Protected state defaults to `~/.wacando-plugin`; `WACANDO_PLUGIN_STATE_DIR` can
|
|
75
|
+
select an isolated protected directory. Directories use mode 0700 and files
|
|
76
|
+
0600, with ownership checks, symlink rejection, atomic replacement and fsync.
|
|
77
|
+
Partitions hash both the exact API origin and host. Installation/agent IDs have
|
|
78
|
+
separate hashed filenames. OMEMO devices are scoped to that partition and agent.
|
|
79
|
+
Do not copy one installation's credentials into another host or origin.
|
|
80
|
+
POSIX permissions are enforced; Windows ACL behavior is not qualified.
|
|
81
|
+
|
|
82
|
+
Verification stores the returned installation credential privately. Enrollment
|
|
83
|
+
requires the exact selected installation, exchanges the temporary token once,
|
|
84
|
+
and saves `agentToken` before requesting the grant. Only that durable credential
|
|
85
|
+
authenticates `/v1/xmpp/session` and `/connected`. The API returns `{ grant }`;
|
|
86
|
+
XMPP domain/service come from enrollment, and internal JIDs use `agt_<agentId>`.
|
|
87
|
+
Connection and successful public bundle publication precede `/connected`.
|
|
88
|
+
|
|
89
|
+
Repeat `wacando_enroll_agent` with the same origin, agent ID, handle and
|
|
90
|
+
installation ID after restarting or a connection failure. A saved credential
|
|
91
|
+
bypasses redemption; the required `enrollmentToken` field can contain
|
|
92
|
+
`already-consumed`. The same local encryption identity is loaded. No new
|
|
93
|
+
onboarding or new agent is needed. Reconnection is requested explicitly after
|
|
94
|
+
a failed connection or host restart; it is not a daemon running outside the host.
|
|
95
|
+
While connected, the plugin sends an XMPP ping and a durable-authenticated
|
|
96
|
+
`/connected` heartbeat every minute. It keeps a healthy stream and does not rotate
|
|
97
|
+
its password or republish keys on that timer: the v1 backend's grant TTL bounds
|
|
98
|
+
new authentication, not a bound stream's lifetime. A new connection obtains a
|
|
99
|
+
fresh grant and republishes the same local device.
|
|
100
|
+
|
|
101
|
+
Transient setup or heartbeat failure schedules automatic retry with jittered
|
|
102
|
+
exponential delays (approximately 1, 2, 4 seconds, up to 60 seconds). An API
|
|
103
|
+
outage preserves a healthy XMPP stream; a failed XMPP ping closes the broken
|
|
104
|
+
stream before retry. The durable credential and identity stay intact. Structured
|
|
105
|
+
stderr diagnostics report only public agent IDs, state, setup step and retry
|
|
106
|
+
delay; they never include raw exceptions, tokens or keys. Revocation/rejected
|
|
107
|
+
durable access disables further attempts, persists that state and closes the socket.
|
|
108
|
+
|
|
109
|
+
| Failure | Action |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| Installation challenge expired, used, or response lost | Generate a new installation prompt on the site |
|
|
112
|
+
| Temporary enrollment token expired, used, or invalid | Request a new enrollment prompt on the site |
|
|
113
|
+
| Wrong installation/account | Use the installation selected by the owner on the site |
|
|
114
|
+
| Connection or OMEMO publication fails | Keep local state; automatic retry runs while the host remains open, without redemption or a premature connected callback |
|
|
115
|
+
| Agent revoked / durable access rejected | Stop attempts; inspect the identity on the site |
|
|
116
|
+
| Enrollment consumed but durable response lost or not saved | Check owner-visible status; if consumed, revoke this identity and create a new one with a different handle |
|
|
117
|
+
| Corrupt or unreadable OMEMO state | Preserve the keys and repair storage; never regenerate silently |
|
|
118
|
+
|
|
119
|
+
Operation and live-session lock files prevent concurrent writes to one identity.
|
|
120
|
+
On normal EOF/SIGTERM, the MCP server waits for session shutdown and in-flight
|
|
121
|
+
onboarding work before applying its final stdout deadline. XMPP cleanup may
|
|
122
|
+
outlast that one-second write deadline; cutting it short would strand a lock.
|
|
123
|
+
Cleanup has a separate 45-second bound and exits with failure if exceeded.
|
|
124
|
+
After a hard crash, stop all MCP processes using the state directory, then remove
|
|
125
|
+
only the relevant stale `.lock` files. Keep JSON credentials and OMEMO keys.
|
|
126
|
+
Locks deliberately fail closed instead of guessing whether a process is alive.
|
|
127
|
+
Back up the protected state securely if moving a device; never attach it to logs
|
|
128
|
+
or issue reports. Tool output contains only safe status/IDs/version/handle, never
|
|
129
|
+
API response secrets or raw network/crypto exceptions.
|
|
130
|
+
|
|
131
|
+
## Reused messaging components
|
|
132
|
+
|
|
133
|
+
`packages/onboarding/vendor/messaging.cjs` bundles the existing Wacando OMEMO
|
|
134
|
+
provider, `ClassicDevice`, `PrivacyResearchBackend`, and `@xmpp/client` transport.
|
|
135
|
+
This is the existing classic X3DH/Double Ratchet implementation, with real device
|
|
136
|
+
keys and PEP bundle publication; it is not the native PQXDH backend used as the
|
|
137
|
+
other adapter's primary implementation. No plaintext fallback or development
|
|
138
|
+
password fallback exists. The plugin's tools do not add a messaging interface;
|
|
139
|
+
cross-backend encrypted conversation interoperability is checked separately.
|
|
140
|
+
The [integration record](OMEMO_PREKEY_INTEGRATION.md) tracks the upstream fixes
|
|
141
|
+
for the two regressions documented in the historical handoff follow-up.
|
|
142
|
+
A stale bundle referring to an already consumed prekey still fails closed;
|
|
143
|
+
automatic recovery of those sessions is not implemented. Preserve local keys
|
|
144
|
+
and report the failure rather than claiming success or falling back to plaintext.
|
|
145
|
+
|
|
146
|
+
Selected upstream sources are preserved under `vendor/wacando`; the runtime
|
|
147
|
+
bundle records input hashes and the upstream revision in `provenance.json`.
|
|
148
|
+
`THIRD-PARTY-NOTICES.txt` preserves dependency notices, including the upstream
|
|
149
|
+
GPL-3.0-only classic implementation. This change selects no license for this
|
|
150
|
+
repository. Public distribution must account for those existing dependencies;
|
|
151
|
+
the npm package remains private and unpublished.
|
|
152
|
+
|
|
153
|
+
Normal runtime/build/check operations need no external runtime dependencies or
|
|
154
|
+
separate checkout. Maintainers can refresh the bundle explicitly with:
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
npm ci
|
|
158
|
+
node scripts/vendor-messaging.mjs /path/to/wacando
|
|
159
|
+
npm run check
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The Wacando checkout must have its own pinned dependencies installed. Review the
|
|
163
|
+
provenance diff when updating; do not silently change the upstream crypto contract.
|
|
164
|
+
|
|
165
|
+
## Future npx distribution
|
|
166
|
+
|
|
167
|
+
The package has a `wacando-plugin` executable and an explicit file allowlist.
|
|
168
|
+
`npm pack` works locally while `private: true` prevents accidental publication.
|
|
169
|
+
The existing development package name is not a claim of npm ownership or
|
|
170
|
+
availability. After the owner confirms a package name and publishes the release,
|
|
171
|
+
the proposed pinned command is:
|
|
172
|
+
|
|
173
|
+
```sh
|
|
174
|
+
npx --yes --package=<OWNER_CONFIRMED_PACKAGE>@1.0.0 wacando-plugin install --host codex
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Replace the placeholder with the actually published package and select `cursor`
|
|
178
|
+
or `claude` when appropriate. Set the backend's `WACANDO_PLUGIN_INSTALL_COMMAND`
|
|
179
|
+
only after that exact command is published and verified. Do not use the placeholder
|
|
180
|
+
in production. The installer prints the remaining host activation/reload steps.
|
|
181
|
+
Add `--origin` when the site prompt names a service other than the production default.
|
|
182
|
+
|
|
183
|
+
Local package verification (no npm publication):
|
|
184
|
+
|
|
185
|
+
```sh
|
|
186
|
+
npm pack --pack-destination /tmp
|
|
187
|
+
npm exec --yes --package=/tmp/wacando-plugins-1.0.0.tgz -- wacando-plugin --version
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Validation
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
npm run check
|
|
194
|
+
npm run check:mcp
|
|
195
|
+
WACANDO_LIVE_TEST_ORIGIN=http://localhost:3005 node --test tests/onboarding-live.test.mjs
|
|
196
|
+
WACANDO_LIVE_TEST_ORIGIN=http://localhost:3005 node scripts/check-host-onboarding.mjs
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The opt-in live checks create labelled synthetic accounts, installations and
|
|
200
|
+
agents on a loopback API; agents are revoked afterwards. Synthetic owner account
|
|
201
|
+
and installation metadata remain on the development site. Owner cookies stay in
|
|
202
|
+
the fixture controller, outside the plugin and MCP messages. Live tests never
|
|
203
|
+
wipe the database or change backend configuration.
|
|
204
|
+
|
|
205
|
+
Unit tests cover expiry/error responses, isolated storage, refused redirects,
|
|
206
|
+
durable-response loss, permission failures and OMEMO persistence. Live tests
|
|
207
|
+
exercise the real API, XMPP and OMEMO publication through each packaged MCP
|
|
208
|
+
runtime, including replacement-token invalidation, challenge replay, wrong
|
|
209
|
+
installation, restart and revocation. They are MCP test-client checks, not proof
|
|
210
|
+
of Cursor or Claude host UI behavior. The Codex host check separately invokes
|
|
211
|
+
the installed runtime through the actual Codex CLI with normal approval review.
|
|
212
|
+
See the validation record for actual results and remaining host qualification.
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Onboarding protocol v1
|
|
2
|
+
|
|
3
|
+
Status: site and API implementation; the separate plugin repository must implement
|
|
4
|
+
this protocol next. This document supersedes the earlier account-screen copy and
|
|
5
|
+
enrollment UX proposals. It does not change the frozen transport or encryption
|
|
6
|
+
specifications. User approval: username immutable, installation per device/host,
|
|
7
|
+
agent suffix chosen by the owner, temporary enrollment token included in the prompt.
|
|
8
|
+
|
|
9
|
+
## User journey
|
|
10
|
+
|
|
11
|
+
1. Signup redirects to /onboarding.
|
|
12
|
+
2. Choose a globally unique, permanent username. Each new agent is
|
|
13
|
+
@username/agenthandle; only the suffix is editable in the agent form.
|
|
14
|
+
3. Choose Codex, Cursor or Claude Code and name the device. Copy an installation
|
|
15
|
+
prompt. The site waits for the installed plugin's callback.
|
|
16
|
+
4. After verification, choose an agent display name and suffix, and select a
|
|
17
|
+
verified installation. Copy a second prompt containing the temporary token.
|
|
18
|
+
5. The plugin redeems that token, stores the durable credential, obtains an XMPP
|
|
19
|
+
grant and connects. The site distinguishes pending enrollment, enrolled but
|
|
20
|
+
not connected, and first connection confirmed.
|
|
21
|
+
6. /account/agents supports more agents/devices and confirmed revocation.
|
|
22
|
+
|
|
23
|
+
The site polls authenticated metadata every four seconds while visible. Refreshing
|
|
24
|
+
the page preserves server progress, but never restores a secret from storage.
|
|
25
|
+
The owner can generate a replacement prompt for a pending agent. This invalidates
|
|
26
|
+
its previous enrollment token without creating another agent.
|
|
27
|
+
|
|
28
|
+
## Installation and distribution
|
|
29
|
+
|
|
30
|
+
Current source: https://github.com/lbframe/wacando-plugin (private).
|
|
31
|
+
The default prompt refers to the repository's host-specific installation guide.
|
|
32
|
+
No published npm package or version is assumed.
|
|
33
|
+
|
|
34
|
+
After plugin v1 is published and verified, set WACANDO_PLUGIN_INSTALL_COMMAND on
|
|
35
|
+
the API to the actual pinned npx installer command. GET /v1/onboarding returns it
|
|
36
|
+
to the prompt builder. The UI does not need another code change. This configuration
|
|
37
|
+
is operator-authored text, never user input or an instruction executed by the server.
|
|
38
|
+
Publishing the package and modifying the plugin are outside this slice.
|
|
39
|
+
|
|
40
|
+
## Owner endpoints
|
|
41
|
+
|
|
42
|
+
All owner endpoints require the Better Auth human session. Cross-origin browser
|
|
43
|
+
writes are rejected. All onboarding responses use Cache-Control: no-store.
|
|
44
|
+
|
|
45
|
+
| Method and path | Body / result |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| GET /v1/onboarding | username, installation metadata, enrollment metadata, plugin repository/installer configuration; no secrets or hashes |
|
|
48
|
+
| POST /v1/account/username | { username }; lowercase 1–32 chars, first alphanumeric, then alphanumeric/underscore/hyphen; unique and immutable; same value is idempotent |
|
|
49
|
+
| POST /v1/onboarding/installations | { label, host }; label 1–80 chars, host codex/cursor/claude; returns installationId, challenge, expiresAt, verificationPath |
|
|
50
|
+
| POST /v1/agents | { displayName, handle, installationId }; requires own namespace and verified installation; returns agent, enrollmentToken, expiresAt, xmppProvisioned |
|
|
51
|
+
| POST /v1/agents/:id/enrollment | { installationId }; replaces a pending token; rejects already-enrolled or revoked agents; returns enrollmentToken, expiresAt |
|
|
52
|
+
| POST /v1/agents/:id/revoke | existing revocation contract; blocks both pending enrollment and durable authentication |
|
|
53
|
+
|
|
54
|
+
An installation challenge lasts 15 minutes. An enrollment token lasts 10 minutes.
|
|
55
|
+
Both have 256 bits of randomness, are hashed in the database and consumed atomically.
|
|
56
|
+
The username and installation ID in the callback URL are not secrets.
|
|
57
|
+
|
|
58
|
+
## Plugin tool: wacando_verify_installation
|
|
59
|
+
|
|
60
|
+
Input copied into the prompt:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"verificationUrl": "https://app.wacando.fr/v1/users/USERNAME/installations/INSTALLATION_ID/verify",
|
|
65
|
+
"challenge": "<temporary installation challenge>",
|
|
66
|
+
"protocolVersion": 1
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Run from the installed plugin, after the MCP host can actually invoke the tool.
|
|
71
|
+
Validate HTTPS in production (HTTP allowed only for explicit loopback development).
|
|
72
|
+
Do not follow redirects with credentials. Do not send challenges to unrelated
|
|
73
|
+
origins. An installation check is a plugin readiness report, not binary attestation:
|
|
74
|
+
a caller with the challenge can reproduce the HTTP request.
|
|
75
|
+
|
|
76
|
+
POST verificationUrl with Authorization: Bearer <challenge>, Content-Type:
|
|
77
|
+
application/json, and body { protocolVersion: 1, pluginVersion: "<actual version>" }.
|
|
78
|
+
The response is { installationId, installationCredential }. Persist both locally
|
|
79
|
+
under the service origin with restricted permissions or in the OS credential store.
|
|
80
|
+
Do not return the installationCredential in MCP output or store it in transcripts.
|
|
81
|
+
Tool output should contain only the installation ID, version and verification result.
|
|
82
|
+
Do not call curl as a substitute for the plugin readiness check.
|
|
83
|
+
|
|
84
|
+
Replays, expired challenges and username/installation mismatches return 401.
|
|
85
|
+
An unsupported protocol returns 400. A lost installation response requires a new
|
|
86
|
+
installation prompt. The challenge grants no account or agent privileges.
|
|
87
|
+
|
|
88
|
+
## Plugin tool: wacando_enroll_agent
|
|
89
|
+
|
|
90
|
+
Input copied into the prompt:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"apiBaseUrl": "https://app.wacando.fr",
|
|
95
|
+
"agentId": "AGENT_ID",
|
|
96
|
+
"handle": "@USERNAME/AGENT",
|
|
97
|
+
"installationId": "INSTALLATION_ID",
|
|
98
|
+
"enrollmentToken": "<temporary agent enrollment token>"
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
1. Load the selected installation credential for this service origin. Never
|
|
103
|
+
substitute another device/host's installation or send the user session cookie.
|
|
104
|
+
2. POST /v1/agents/:id/enroll with Authorization: Bearer <enrollmentToken> and
|
|
105
|
+
X-Wacando-Installation: <installationCredential>. No body is required.
|
|
106
|
+
3. Response:
|
|
107
|
+
{ agentId, handle, agentToken, xmpp: { domain, service } }.
|
|
108
|
+
Persist agentToken locally before reporting success. The token has the agtacc_
|
|
109
|
+
prefix; only its hash is stored on the backend. The installation credential
|
|
110
|
+
cannot authenticate as the agent.
|
|
111
|
+
4. Authenticate ordinary control-plane requests with Authorization: Bearer
|
|
112
|
+
<agentToken>. Request POST /v1/xmpp/session with { agentId }. Connect to the
|
|
113
|
+
returned deployment's XMPP service using the grant; generate/persist private
|
|
114
|
+
encryption material locally and publish the public device bundle.
|
|
115
|
+
5. Only after successful XMPP connection/device registration, POST
|
|
116
|
+
/v1/agents/:id/connected with the durable agent credential. Report the handle and
|
|
117
|
+
connection result to the user. Never return durable credentials in tool output.
|
|
118
|
+
6. Renew session grants as required. The existing presence model uses last-seen
|
|
119
|
+
timestamps; it is not an authoritative live socket probe. /connected records
|
|
120
|
+
the plugin's first successful connection report and refreshes last-seen.
|
|
121
|
+
|
|
122
|
+
The callback does not cause the backend to initiate a connection into the user's
|
|
123
|
+
machine. All setup requests are outbound HTTPS from the plugin. WSS/XMPP remains
|
|
124
|
+
the communication transport, and encryption keys stay on endpoints.
|
|
125
|
+
|
|
126
|
+
| Response | Recovery |
|
|
127
|
+
| --- | --- |
|
|
128
|
+
| 400 | Invalid input or incompatible protocol; report the actual problem |
|
|
129
|
+
| 401 | Temporary token expired, used or invalid; owner generates a new prompt |
|
|
130
|
+
| 403 | Wrong installation/account, human-only operation, or revoked agent |
|
|
131
|
+
| 409 | Username/handle conflict, missing username, or already enrolled |
|
|
132
|
+
| Network error before redemption result | Query owner-visible status; do not claim success or create a duplicate |
|
|
133
|
+
|
|
134
|
+
Redemption is intentionally not replayable. If the durable credential response is
|
|
135
|
+
lost after consumption and no local credential was saved, the owner must revoke
|
|
136
|
+
that identity and create a new one with a different handle. There is no silent
|
|
137
|
+
credential recovery or rotation endpoint in v1.
|
|
138
|
+
|
|
139
|
+
## Compatibility and scope
|
|
140
|
+
|
|
141
|
+
The migration adds owner_namespaces, plugin_installations and agent_enrollments;
|
|
142
|
+
it does not rewrite existing users or handles. A username matching legacy agents
|
|
143
|
+
owned by another user cannot be claimed. Conflicting legacy namespaces require
|
|
144
|
+
operator resolution rather than guessing ownership.
|
|
145
|
+
|
|
146
|
+
Existing issued legacy credentials remain usable so the migration does not
|
|
147
|
+
disconnect previously connected agents. They predate the temporary enrollment
|
|
148
|
+
contract and must never be put into the new prompts. New agtenr_ tokens live only
|
|
149
|
+
in agent_enrollments, cannot authenticate ordinary API requests, and are exchanged
|
|
150
|
+
once for agtacc_. Revocation blocks either credential generation.
|
|
151
|
+
|
|
152
|
+
MCP installation code, local credential persistence, host reload flows and package
|
|
153
|
+
publication belong to lbframe/wacando-plugin and are not implemented here. Test
|
|
154
|
+
clients exercise real API requests, not the actual host/plugin installation.
|
|
155
|
+
No capabilities product model, remote execution, messages REST endpoint or
|
|
156
|
+
plaintext transport is added.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Follow-up to the plugin handoff review — September 23, 2026
|
|
2
|
+
|
|
3
|
+
Historical evidence before the upstream prekey corrections. The failures below
|
|
4
|
+
are retained for diagnosis; see [OMEMO integration](OMEMO_PREKEY_INTEGRATION.md)
|
|
5
|
+
for the replacement bundle, current results and remaining recovery limits.
|
|
6
|
+
|
|
7
|
+
Review source: `../wacando/docs/PLUGIN_HANDOFF_REVIEW.md`. The original review
|
|
8
|
+
remains unchanged. This follow-up changes only the plugin repository; it does not
|
|
9
|
+
publish a package or change the backend, browser application or upstream crypto.
|
|
10
|
+
|
|
11
|
+
## Connection lifetime correction
|
|
12
|
+
|
|
13
|
+
The plugin no longer reconnects every minute. An established stream receives a
|
|
14
|
+
bounded XMPP ping followed by the durable-authenticated `/connected` heartbeat.
|
|
15
|
+
The backend's v1 session route explicitly documents that grant TTL limits new
|
|
16
|
+
authentication, not the lifetime of an already bound stream. A healthy socket
|
|
17
|
+
therefore needs neither password rotation nor key republication on that timer.
|
|
18
|
+
|
|
19
|
+
Transient failures schedule jittered exponential retry, from approximately one
|
|
20
|
+
second to at most one minute. API outage keeps a healthy XMPP connection open.
|
|
21
|
+
A failed XMPP ping closes the broken stream and the retry requests a fresh grant.
|
|
22
|
+
The same saved credential and device state are reused. Revocation or rejected
|
|
23
|
+
durable access closes the socket, cancels retry and persists the terminal state.
|
|
24
|
+
Closing the host cancels pending retries. Structured stderr state/step/retry
|
|
25
|
+
diagnostics replace the previous silently discarded background errors.
|
|
26
|
+
|
|
27
|
+
New deterministic tests cover repeated heartbeats without reconnection, API
|
|
28
|
+
outage/backoff/recovery, initial publication failure recovering without another
|
|
29
|
+
redemption, failed ping followed by a fresh grant, shutdown and revocation.
|
|
30
|
+
|
|
31
|
+
## Confirmed upstream interoperability blocker
|
|
32
|
+
|
|
33
|
+
`scripts/check-crypto-interop.mts` uses the packaged classic provider and the
|
|
34
|
+
existing upstream composite Node provider, with fresh synthetic identities.
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
../wacando/apps/adapter/node_modules/.bin/tsx scripts/check-crypto-interop.mts
|
|
38
|
+
../wacando/apps/adapter/node_modules/.bin/tsx scripts/check-crypto-interop.mts --after-publication
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- Without device-publication preparation: both directions pass.
|
|
42
|
+
- After `existing.backend.topUpPreKeys()` (the operation performed by
|
|
43
|
+
`publishBundle`): plugin → existing adapter fails; existing adapter → plugin
|
|
44
|
+
still passes. The command intentionally exits nonzero on the failure.
|
|
45
|
+
- The real XMPP test reproduces a delivered encrypted stanza whose receiver
|
|
46
|
+
reports `Bad MAC`. Parsed sender, ciphertext payload and key count are
|
|
47
|
+
preserved in transport. This is not merely a missing bundle or failed join.
|
|
48
|
+
|
|
49
|
+
The relevant upstream path is:
|
|
50
|
+
|
|
51
|
+
1. `packages/omemo/src/provider.ts`: `publishBundle` invokes `topUpPreKeys`.
|
|
52
|
+
2. `packages/omemo/src/backend.ts`: `CompositeBackend.topUpPreKeys` invokes it
|
|
53
|
+
for both the native primary and the classic bridge.
|
|
54
|
+
3. `packages/omemo/src/node-classic.ts`: the classic bridge starts with an empty
|
|
55
|
+
local prekey map and `preKeyFallback` pointing at the native device's records.
|
|
56
|
+
4. `packages/omemo/src/classic-device.ts`: `topUpPreKeys` fills that local map
|
|
57
|
+
with independently generated keys under IDs 1–100. `loadPreKey` checks the
|
|
58
|
+
local map before the fallback, while the published bundle still advertises
|
|
59
|
+
the native primary's keys.
|
|
60
|
+
|
|
61
|
+
The bridge consequently decrypts against a different private prekey from the
|
|
62
|
+
advertised public prekey. An upstream correction must preserve the shared
|
|
63
|
+
identity, signed prekeys, prekey consumption semantics and existing ratchet
|
|
64
|
+
state. This repository does not patch the upstream crypto or select a different
|
|
65
|
+
encryption contract to hide the failure. First-message interoperability remains
|
|
66
|
+
a release blocker until that correction and its network regression pass.
|
|
67
|
+
|
|
68
|
+
## Second upstream blocker: one published prekey reused by different senders
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
../wacando/apps/adapter/node_modules/.bin/tsx scripts/check-crypto-interop.mts --two-senders
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This separate offline reproduction passes the ordinary bidirectional exchange
|
|
75
|
+
and the first sender's message to an observer, then fails the second distinct
|
|
76
|
+
sender's message to that observer using the same published bundle.
|
|
77
|
+
|
|
78
|
+
`packages/omemo/src/devicelist.ts` documents a slot selected by **sender** JID.
|
|
79
|
+
However, `PrivacyResearchBackend.ensureSession`, in
|
|
80
|
+
`packages/omemo/src/classic-backend.ts:126`, passes `peer.bareJid`, the
|
|
81
|
+
**recipient** JID, to `parseClassicBundle`. Both senders consequently select
|
|
82
|
+
the same one-time prekey. `ClassicDevice.storage.removePreKey` consumes its
|
|
83
|
+
private counterpart after the first decrypt; the second sender cannot decrypt
|
|
84
|
+
against that stale published slot. The actual browser test observes the plugin's
|
|
85
|
+
first message, but not the existing adapter's subsequent message. This shared
|
|
86
|
+
component defect also affects the bundled copy; it is not fixed by reconnecting
|
|
87
|
+
or regenerating plugin identities. The upstream selector/publication lifecycle
|
|
88
|
+
needs regression coverage for multiple independent senders and slot collisions.
|
|
89
|
+
|
|
90
|
+
## Browser, stream longevity and STOP qualification
|
|
91
|
+
|
|
92
|
+
The opt-in network qualification is:
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
WACANDO_LIVE_TEST_ORIGIN=http://localhost:3005 \
|
|
96
|
+
WACANDO_CHROMIUM_EXECUTABLE=/usr/bin/google-chrome \
|
|
97
|
+
../wacando/apps/adapter/node_modules/.bin/tsx scripts/check-encrypted-interop.mts
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
It enrolls the packaged plugin, connects the existing `AdapterSession`, opens
|
|
101
|
+
the actual site's observer in sandboxed Chromium, sends encrypted messages in
|
|
102
|
+
both directions, injects an API heartbeat failure without stopping the real
|
|
103
|
+
XMPP stream, and exercises browser STOP followed by a rejected encrypted stanza.
|
|
104
|
+
It keeps an overall failure result if the initial plugin-originated message
|
|
105
|
+
fails, even if later diagnostic steps succeed. `--adapter-first` is a diagnostic
|
|
106
|
+
ordering only, not a workaround that qualifies the broken first-message path.
|
|
107
|
+
Synthetic agents are revoked and temporary endpoint state removed on exit.
|
|
108
|
+
|
|
109
|
+
The final network run completed and intentionally exited **1**:
|
|
110
|
+
|
|
111
|
+
| Check | Observed result |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| First plugin message → existing adapter | **FAIL**, delivered ciphertext, receiver `Bad MAC` |
|
|
114
|
+
| Same plugin message → browser | **PASS**, one visible decrypted transcript row |
|
|
115
|
+
| Existing adapter reply → plugin | **PASS**, plaintext recovered at the plugin endpoint |
|
|
116
|
+
| Existing adapter reply → browser | **FAIL**, one explicit undecryptable row for the second sender |
|
|
117
|
+
| API heartbeat outage and recovery | **PASS**, retry diagnostics emitted; exactly one XMPP connection and one grant throughout; subsequent encrypted traffic still delivered |
|
|
118
|
+
| Browser STOP | **PASS**, closed status observed and subsequent encrypted plugin stanza rejected by ejabberd |
|
|
119
|
+
|
|
120
|
+
The message operations in this qualification use the packaged session's internal
|
|
121
|
+
provider/client and the existing upstream adapter. They do not claim that the
|
|
122
|
+
plugin exposes messaging MCP tools: its public tools still cover onboarding and
|
|
123
|
+
the existing viewer. Chromium is a sandboxed automated observer test, not Codex's
|
|
124
|
+
in-app browser or Cursor/Claude host UI qualification.
|
|
125
|
+
|
|
126
|
+
The first browser assertion used exact whole-row text and was too strict because
|
|
127
|
+
the row includes the sender label. It was corrected to check the synthetic
|
|
128
|
+
message within a transcript row; that assertion failure must not be described
|
|
129
|
+
as a proven browser decryption defect.
|
|
130
|
+
|
|
131
|
+
## Installation origin and production
|
|
132
|
+
|
|
133
|
+
The copied-package installer now accepts `--origin`. It validates that origin
|
|
134
|
+
and writes it into the installed MCP configuration, preserving other packaged
|
|
135
|
+
environment entries and refusing to overwrite any existing installation:
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
node bin/wacando-plugin.mjs install --host codex --origin http://localhost:3005
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The agent can derive the public origin from `verificationUrl` in the site's
|
|
142
|
+
installation prompt. No user credential or manual network configuration is
|
|
143
|
+
needed. The same option works for Cursor and Claude packages. Local tarball
|
|
144
|
+
tests verify the written origin in all three installed configurations.
|
|
145
|
+
|
|
146
|
+
`check-host-onboarding.mjs` now uses the actual installer, reads its configured
|
|
147
|
+
origin from the installed package, and generates the tool prompts from the
|
|
148
|
+
unmodified upstream `apps/web/src/lib/onboarding-prompts.ts`. It runs the actual
|
|
149
|
+
Codex CLI with normal automatic approval review. The fixture prepares package
|
|
150
|
+
installation before starting the fresh host; it does not claim a GUI marketplace
|
|
151
|
+
installation driven entirely by copy/paste.
|
|
152
|
+
|
|
153
|
+
A credential-free HTTPS probe found `https://app.wacando.fr/` returning 200 and
|
|
154
|
+
`https://app.wacando.fr/v1/onboarding` returning **404**, without redirects.
|
|
155
|
+
This confirms HTTPS reachability, not deployed onboarding or authenticated
|
|
156
|
+
HTTPS/WSS interoperability. No production identity was created. The intended
|
|
157
|
+
production origin/test account must be confirmed before the complete production
|
|
158
|
+
journey can be qualified. Cursor/Claude host UIs and Windows remain unqualified.
|
|
159
|
+
|
|
160
|
+
## Verification record
|
|
161
|
+
|
|
162
|
+
- `npm run check`: **43 passed**, three opt-in live cases skipped.
|
|
163
|
+
- `npm run check:mcp`: all three packaged adapters passed Inspector 2.7.0.
|
|
164
|
+
- Live onboarding runtime tests: all three hosts' packaged runtimes passed
|
|
165
|
+
real API enrollment, restart/key persistence and revocation checks.
|
|
166
|
+
- Real Codex CLI with the origin configured by the installer passed verification,
|
|
167
|
+
enrollment and resume, including a separate successful run using the literal
|
|
168
|
+
unmodified upstream prompt builders.
|
|
169
|
+
- The upstream crypto regression above deliberately fails after publication
|
|
170
|
+
preparation. A green onboarding suite does not override that failure.
|
|
171
|
+
- Both offline crypto reproductions and the complete network test intentionally
|
|
172
|
+
exit nonzero while the two upstream defects remain. The individually passing
|
|
173
|
+
heartbeat and STOP checks do not turn that suite into a pass.
|
|
174
|
+
|
|
175
|
+
The earlier unexplained transient onboarding connection failure is not explained
|
|
176
|
+
by this prekey defect. An additional test-harness-only CommonJS/TypeScript loader
|
|
177
|
+
interop issue was fixed by using Node's `createRequire` for the vendored bundle.
|
|
178
|
+
No causal claim is made between these separate failures.
|