Skip to content

Commit f3bb146

Browse files
ioannischtzclaude
andauthored
feat(chat-app): fully-local devstack stack with local Seal (#73)
* build(chat-app): published SDK (Mode A) + devstack devDeps + pnpm config - depend on published @mysten/sui-stack-messaging (drop link: + build:deps) - add devstack/dev-wallet/signers devDependencies (chat-app only) - move pnpm settings (onlyBuiltDependencies, overrides) to pnpm-workspace.yaml so pnpm v11 reads them Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(chat-app): fully-local devstack stack with local Seal Run the whole stack on localnet via @mysten-incubation/devstack — local Sui + local-keygen Seal + published Move package + dev-wallet — so message decryption works with no testnet dependency. Validated create -> send -> decrypt. - devstack.config.ts materializes gitignored, unpublished copies of sui_groups/ messaging so they bundle into one local package on publish - virtual:devstack-app-config shim + src/lib/devstack-config.ts consume the generated config (dev-only gated; prod/testnet build stays incubation-free), register the dev-wallet, and recover on-chain ids via GraphQL - one local Seal server + sealThreshold 1; serialize wallet signs (DevWallet allows one pending sign); add a localnet dapp-kit network Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(devstack): de-draft spin-up-local-devstack + chat-app integration docs - verified spin-up-local-devstack SKILL.md (publish, Seal, dev-wallet, relayer) - chat-app/docs/DEVSTACK.md: what the integration does and why - reference/NOTES.md: friction log + links to upstream devstack/dev-wallet docs (not vendored) - de-draft the skill references in AGENTS.md / chat-app/AGENTS.md Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(chat-app): bundle suins locally for devstack publish Address PR #73 review: - materialize suins as a stripped local copy; its committed Move.lock carries an [env.testnet] published-id that leaked through the git dep and made the -e testnet build link a testnet id absent on localnet - label the local GraphQL client 'localnet' - scope the full-local Walrus archival path as a follow-up Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 8c23aa1 commit f3bb146

17 files changed

Lines changed: 3569 additions & 87 deletions

File tree

.claude/skills/spin-up-e2e-stack/SKILL.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ Three services, three terminals. Run in this order so each service is ready befo
2626

2727
> **Use testnet, not mainnet, for this whole flow.** This skill assumes a dev wallet funded from the testnet faucet. Every "Create a group" / "Send a message" in the smoke test below mints real on-chain state on whichever network your relayer + chat-app are pointed at. Mainnet group/message creation costs real SUI, persists permanently, and may be visible to real users if your chat-app's group-discovery surface exposes it. Keep `GROUPS_PACKAGE_ID` (relayer) + `VITE_*` package configs (chat-app) on testnet for development.
2828
29+
> **Want fully-local (localnet with your own contracts)?** This skill is testnet-first. On a localnet + testnet-Seal hybrid, **message decryption does not work** (Seal key servers run against testnet and can't authorize localnet group objects), GraphQL must be locally enabled for group discovery, and Walrus is testnet-only. If you need an all-local stack with working encryption, see [`spin-up-local-devstack`](../spin-up-local-devstack/SKILL.md), which runs a **local Seal key server** via `@mysten-incubation/devstack`. For a manual localnet bring-up without devstack, note these gotchas surfaced in practice:
30+
> - **Relayer gRPC on localnet is the fullnode RPC port `:9000`**, not `:9124` (the Consistent Store, which 404s on `subscribe_checkpoints`).
31+
> - **Publishing the canonical package to localnet** needs the suins MVR dep patched to git + `sui client test-publish --publish-unpublished-deps` (mirror `ts-sdks/packages/sui-stack-messaging/test/helpers/localnet/localnet-setup.ts`).
32+
> - **The chat-app must pass `packageConfig.permissionedGroups`** (the localnet `sui_groups` IDs) or group ops auto-detect testnet and fail. The code reads `VITE_MESSAGING_*` (not the stale `VITE_MESSAGING_GROUPS_*` in `.env.example`).
33+
2934
## Recommended path: Docker for the two backend services
3035

3136
**Prefer Docker for the relayer and the walrus-indexer.** Both ship Dockerfiles; containers avoid host-toolchain friction. Steps 1–3 below are the no-Docker (host) alternative. The chat-app is a Vite dev server with no Dockerfile, so it always runs on the host (Step 3).
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
name: spin-up-local-devstack
3+
description: Use when the user wants a FULLY-LOCAL stack (no testnet dependency) for Sui Stack Messaging — including a LOCAL Seal key server so message decryption works on localnet. Uses @mysten-incubation/devstack to compose a local Sui node + local-keygen Seal + (optional) local Walrus + published Move packages + the chat-app from one config file. The localnet counterpart to spin-up-e2e-stack (which is testnet-first and cannot decrypt on localnet). Requires Docker + Node >= 24. Trigger phrases - "fully local stack", "localnet with working Seal", "local seal key server", "devstack", "no testnet dependency", "local encryption", "decrypt on localnet", "all-local messaging stack".
4+
---
5+
6+
# Spin up a fully-local stack with devstack (incl. local Seal)
7+
8+
A one-command, all-local Sui Stack Messaging stack via `@mysten-incubation/devstack`: local Sui node +
9+
a **local Seal key server** + the messaging Move package + a browser dev-wallet + the chat-app. The
10+
payoff is that message **decryption works fully locally** — the testnet-first
11+
[`spin-up-e2e-stack`](../spin-up-e2e-stack/SKILL.md) can't decrypt on localnet (Seal has no localnet;
12+
the canonical key servers can't authorize localnet group objects).
13+
14+
This was validated end-to-end (`create → send → DECRYPT`). The chat-app-side integration is documented
15+
in [`chat-app/docs/DEVSTACK.md`](../../../chat-app/docs/DEVSTACK.md); the friction log + upstream doc
16+
links are in [`reference/NOTES.md`](./reference/NOTES.md).
17+
18+
## Requirements
19+
20+
- **Docker, running.** sui / seal run as containers; first boot pulls images (slow).
21+
- **Node >= 24** (devstack `engines`). With nvm: `nvm install 24 && nvm use 24`.
22+
- **pnpm 10.x for installs.** On pnpm v11 a fresh install trips the esbuild build gate and the
23+
`minimumReleaseAge` floor on devstack's fresh transitive deps. Use `npx pnpm@10 install`. See
24+
[`docs/pnpm-v11-troubleshooting.md`](../../../docs/pnpm-v11-troubleshooting.md).
25+
- **No native localnet on `:9000`.** Stop any `sui start` first.
26+
- The incubation deps stay **chat-app devDependencies only** (never the canonical SDK).
27+
28+
## Run
29+
30+
```bash
31+
cd chat-app
32+
npx pnpm@10 install # devDeps: @mysten-incubation/devstack@0.1.1, @mysten-incubation/dev-wallet@0.3.0, @mysten/signers@1.0.5
33+
pnpm devstack up # sui + local Seal + publish + codegen + serve (add --renderer plain for clean logs)
34+
# offline sanity check (no Docker): pnpm devstack config
35+
```
36+
37+
Open the printed `http://dev.chat-app-local.chat-app.localhost:5175`, connect the **Dev Wallet**
38+
(funded `publisher`/`alice`/`bob`), create a group, send, refresh → it decrypts. Send/decrypt also need
39+
the relayer (below).
40+
41+
## How it fits together
42+
43+
`devstack up` brings up: Sui node → publisher account → messaging package publish → local-keygen Seal →
44+
dev-wallet server → chat-app (Vite), writing typed config to `chat-app/src/generated/` (gitignored).
45+
The chat-app consumes it through `vite.config.ts` (`devstackVitePlugin()` aliases `@generated`; a
46+
`virtual:devstack-app-config` shim keeps it dev-only) and `src/lib/devstack-config.ts`. Full walkthrough:
47+
[`chat-app/docs/DEVSTACK.md`](../../../chat-app/docs/DEVSTACK.md).
48+
49+
The load-bearing, non-obvious bits (all handled in `chat-app/devstack.config.ts` + `devstack-config.ts`):
50+
51+
- **Publishing the package.** devstack does one `Transaction.publish({ modules })`, which *merges*
52+
bundled unpublished deps into one package. `sui_groups` ships a committed `Published.toml`, so the
53+
`-e testnet` build links its testnet id (absent on localnet) instead of bundling. Fix: materialize a
54+
gitignored copy of `sui_groups` with `Published.toml`/`Move.lock` stripped + a local Move dep, patch
55+
`suins` MVR→git, strip messaging's `Published.toml`. Net: messaging + sui_groups merge into one local
56+
package id (so `messaging` and `permissionedGroups` configs share it). The app recovers the
57+
namespace/version singletons + the groups id from the publish tx via GraphQL at bootstrap.
58+
- **Seal: one server, `sealThreshold: 1`.** Two local-keygen servers collide in codegen in 0.1.1.
59+
- **Dev-wallet: register it yourself.** `devstackVitePlugin()` only aliases `@generated` — it does NOT
60+
inject a wallet. devstack runs the wallet *server* (funded accounts); the app builds a
61+
`DevstackSignerAdapter` from `@generated/dapp-kit/config`, `register()`s a `DevWallet`, and
62+
`mountDevWallet()`s the panel. Serialize sign calls (the DevWallet allows one pending sign).
63+
64+
## Relayer
65+
66+
devstack does not run the reference relayer; send/fetch go through it. Run it separately
67+
([`spin-up-relayer`](../spin-up-relayer/SKILL.md)) on the host, pointed at the **direct host-published
68+
validator port** (not the Traefik-routed `:9000`, which 400s on gRPC):
69+
70+
```bash
71+
docker port <devstack-…-sui-validator> 9000 # e.g. 127.0.0.1:51000
72+
# relayer/.env: SUI_RPC_URL=http://127.0.0.1:51000 ; GROUPS_PACKAGE_ID=<merged id from src/generated/packages.ts>
73+
cd relayer && cargo run # :3000 ; the chat-app reads VITE_RELAYER_URL (default localhost:3000)
74+
```
75+
76+
## Walrus (optional)
77+
78+
Walrus is **off the critical path for the create → send → decrypt loop**: decryption never touches
79+
it (delivery = relayer store + on-chain refs; Walrus is recovery / attachments only), so leaving it
80+
out doesn't compromise local decryption. Only message **attachments** need it.
81+
82+
The seam that stays non-local is **archival** — the reference relayer archives to its default
83+
**testnet** Walrus. Making *that* local is a tracked follow-up (not done here): devstack offers
84+
`walrus({ local: { nodeCount, shards } })` + `walCoin`, but the relayer + chat-app talk **HTTP** to a
85+
publisher/aggregator gateway (not the Walrus SDK) — whether devstack's local Walrus exposes those is
86+
the open question — and it also needs repointing the relayer's `WALRUS_PUBLISHER_URL`/`AGGREGATOR_URL`,
87+
enabling attachments (off in devstack mode), and wiring the indexer + SDK `RecoveryTransport`. To
88+
experiment now, add `walrus({ local })` + `walCoin` to `devstack.config.ts` and wire `VITE_WALRUS_*`.
89+
90+
## Gotchas (full list in `reference/NOTES.md`)
91+
92+
- **First boot is slow** (image pulls). `.devstack/` + `src/generated/` are gitignored (regenerated each `up`).
93+
- **Reset:** `devstack wipe --yes`; hard Docker reset `docker rm -f $(docker ps -aq --filter name=devstack)`
94+
(`devstack prune` only removes idle groups). Re-emit codegen: `devstack apply`.
95+
- **"A signing request is already pending"** = concurrent signs vs the DevWallet's one-pending model → serialize app-side.
96+
- **Connect hangs at "Confirm connection in the wallet"** = no `mountDevWallet()`.
97+
- **Relayer "grpc-status header missing, HTTP 400"** = gRPC through Traefik → use the host-published port.
98+
99+
## Cross-links
100+
101+
- Testnet-first / manual localnet path: [`spin-up-e2e-stack`](../spin-up-e2e-stack/SKILL.md).
102+
- Run the relayer: [`spin-up-relayer`](../spin-up-relayer/SKILL.md).
103+
- Why Seal can't work on a localnet + testnet-Seal hybrid: [`debug-encryption-flow`](../debug-encryption-flow/SKILL.md) (Stage 3).
104+
- devstack docs: <https://github.com/MystenLabs/ts-sdks-incubation/tree/main/packages/docs/content/devstack>
105+
· dev-wallet docs: <https://github.com/MystenLabs/ts-sdks-incubation/tree/main/packages/docs/content/dev-wallet>

0 commit comments

Comments
 (0)