4.6 KiB
openhuman ↔ tiny.place messaging e2e
End-to-end coverage for the tiny.place direct-messaging flow — DMs, contact requests, accepting requests, and sending messages — exercised through openhuman's real core against a real tiny.place backend. Two layers:
| Layer | File | What it drives |
|---|---|---|
| Core | messaging.e2e.mjs |
Two real openhuman-core processes talking to each other over the openhuman.tinyplace_* JSON-RPC surface (the exact API the desktop UI calls via core_rpc_relay). |
| UI | ../../app/test/playwright/specs/tinyplace-messaging.spec.ts |
The web build of the app (Messaging screen) driving the same flow through the browser, with a second core as the peer. |
Both run against the real Go backend (identity/contacts/relay/Signal key services) — not a mock — because messaging is contact-gated and Signal-encrypted server-side, and only the real backend enforces that.
What the core suite proves
Each openhuman-core derives its tiny.place identity (a base58 Solana
cryptoId) from its wallet mnemonic, so two cores with two fresh mnemonics are
two distinct agents. The suite walks the full lifecycle:
- Identities — each core boots a distinct, message-ready identity (published signed pre-key, one-time pre-keys, and directory encryption key).
- Contact gate — a DM between non-contacts is refused (
not_a_contact). - Send request — Alice sends a contact request; Bob sees it
pending. - Accept request — Bob accepts; both sides see a mutual
acceptedcontact. - Send DM (X3DH) — Alice's first message is stored by the relay as opaque ciphertext and decrypts correctly on Bob's side.
- Reply (Double Ratchet) — Bob's reply decrypts on Alice's side.
- In-session DM — a follow-up message still decrypts.
Run it
# Core layer (two openhuman-core processes over JSON-RPC). Brings up an isolated
# backend (mongo+redis+backend, static payment verifier) if one isn't already
# reachable, builds the core if needed, then runs the node:test suite.
./run.sh
# UI layer (Playwright against the web build). Same backend handling; boots the
# app's core + web host and a peer core, then drives the Messaging screen.
./run-ui.sh
Or, if you already have a backend and a built core:
TINYPLACE_API_BASE_URL=http://localhost:18080 node --test messaging.e2e.mjs
What the UI suite proves
Driven through the real Messaging screen (/agent-world/messaging) of the
web build, against the same real backend, with a second core as the peer:
- Send — typing a recipient + message and hitting Send emits an end-to-end encrypted DM that the real peer core receives and decrypts.
- Receive — a reply sent by the peer renders as plaintext in the UI thread.
Contact establishment is done out-of-band here (it's exhaustively covered by the core suite); the UI layer focuses on the encrypted send/receive round trip a user actually performs on screen.
Requirements
- Docker (only if you want
run.shto auto-start the backend). - A built
openhuman-corebinary (cargo build --bin openhuman-core;run.shbuilds it if missing). On Apple Silicon prefix withGGML_NATIVE=OFF.
Env knobs
| Var | Default | Meaning |
|---|---|---|
TINYPLACE_API_BASE_URL |
http://localhost:18080 |
Backend base URL both cores point at. |
OPENHUMAN_CORE_BIN |
target/debug/openhuman-core |
Path to the core binary. |
MANAGE_STACK |
1 |
0 disables auto start/stop of the backend. |
BACKEND_PORT |
18080 |
Host port for the managed backend. |
VERBOSE |
– | 1 streams each core's stdout/stderr. |
Why two cores instead of one core + a mock peer
The core's tiny.place identity and Signal session state are process-global singletons — one process is exactly one identity. A real two-party round trip therefore needs two processes. Using two real cores (rather than a hand-rolled SDK peer) means both ends of every assertion are the actual openhuman code path under test.
Notes
- Every run generates fresh mnemonics (see
lib/mnemonic.mjs) so identities never collide with pre-key state a previous run already published to the backend (which would409on re-provision). No npm install is needed — the BIP-39 generator is dependency-free. - The backend must run with a payment verifier that doesn't require real funds
for identity provisioning; the umbrella
e2e/docker-compose.e2e.ymloverlay (static verifier) is whatrun.shuses.