Skip to content

feat(chat-app): fully-local devstack stack with local Seal#73

Merged
ioannischtz merged 4 commits into
mainfrom
devstack-localnet
Jun 10, 2026
Merged

feat(chat-app): fully-local devstack stack with local Seal#73
ioannischtz merged 4 commits into
mainfrom
devstack-localnet

Conversation

@ioannischtz

@ioannischtz ioannischtz commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Fully-local Sui Stack Messaging stack via @mysten-incubation/devstack — local Sui + a local-keygen Seal key server + the published Move package + a dev-wallet + the chat-app, from one config. Closes the gap where a localnet-Sui + testnet-Seal hybrid can't decrypt localnet group objects. Validated end-to-end: create → send → DECRYPT, fully local.

What's here

  • chat-app/devstack.config.ts — publishes the canonical package on localnet by materializing gitignored, unpublished copies of sui_groups/messaging (they bundle into one local package on publish).
  • vite.config.ts shim + src/lib/devstack-config.ts — consume the generated config (dev-only gated; the prod/testnet build stays incubation-free) and register the dev-wallet.
  • One local Seal server + sealThreshold: 1; serialized wallet signs (the DevWallet allows one pending sign).
  • chat-app now depends on the published @mysten/sui-stack-messaging (Mode A); pnpm settings moved to pnpm-workspace.yaml.
  • Docs: verified spin-up-local-devstack skill, chat-app/docs/DEVSTACK.md (integration), reference/NOTES.md (friction log + links to the upstream docs, not vendored).

Run

cd chat-app && npx pnpm@10 install && pnpm devstack up (Docker + Node ≥ 24). The reference relayer runs separately for send/fetch — see chat-app/docs/DEVSTACK.md.

Follow-up

Migrate the chat-app off the deprecated @mysten/dapp-kit to @mysten/dapp-kit-react (gRPC-native) — a separate PR; browser-gRPC-on-localnet is already proven working here, so its main risk is retired.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jun 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
groups-sdk Ready Ready Preview, Comment Jun 10, 2026 8:28am

Request Review

Base automatically changed from sew-958-make-the-messaging-sdk-llm-agent-ready to main June 8, 2026 11:24
ioannischtz and others added 3 commits June 8, 2026 17:48
- 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>
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>
…n 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>
@ioannischtz ioannischtz changed the title docs: DRAFT spin-up-local-devstack skill + devstack config feat(chat-app): fully-local devstack stack with local Seal Jun 8, 2026
@ioannischtz ioannischtz marked this pull request as ready for review June 8, 2026 14:51
@ioannischtz

Copy link
Copy Markdown
Collaborator Author

Follow-ups (separate PRs)

This PR validates fully-local messaging (create → send → decrypt). Two follow-ups carry the rest:

1. Migrate the chat-app @mysten/dapp-kit@mysten/dapp-kit-react. The old kit is deprecated (JSON-RPC only, no gRPC/GraphQL); the new one is gRPC-native and makes the dev-wallet first-class. Browser-gRPC-on-localnet is already proven working here, so the migration's main risk is retired. ~M-tier (9 files); the dev-wallet wiring is identical on both kits, so it's intentionally decoupled from this PR.

2. Full-local Walrus / recovery e2e. Today the relayer archives to testnet Walrus (its defaults), and decryption never touches Walrus (delivery = relayer store + on-chain refs; Walrus is recovery-only) — so it's off the critical path. Going fully local needs:

  • a local Walrus cluster (devstack walrus({ local })) plus a local publisher/aggregator HTTP gateway (relayer + chat-app talk HTTP, not the Walrus SDK) — open question whether devstack's local Walrus exposes those;
  • repointing the relayer's WALRUS_PUBLISHER_URL/AGGREGATOR_URL (else cross-network archival to testnet);
  • enabling attachments (currently off in devstack mode);
  • the bulk: wiring the walrus-discovery-indexer + the SDK's RecoveryTransport into the chat-app (the demo uses neither today);
  • porting group discovery to the newer localnet GraphQL schema (transaction vs transactionBlock).

@nikos-kitmeridis nikos-kitmeridis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved but claude made this change into chat-app.config.ts in order to set the whole stack up properly:

Index: chat-app/devstack.config.ts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/chat-app/devstack.config.ts b/chat-app/devstack.config.ts
--- a/chat-app/devstack.config.ts	(revision 67d7bb0d98eae88b763445521298683e6b21038d)
+++ b/chat-app/devstack.config.ts	(date 1780993319909)
@@ -51,8 +51,11 @@
 // untouched), mirroring the localnet test path's end-state
 // (`sui client test-publish` against the live chain, where sui_groups is
 // unpublished and gets bundled):
-//   - `suins = { r.mvr = "@suins/core" }`  ->  git (MVR doesn't resolve on localnet;
-//     this suins rev ships no Published.toml, so it bundles as-is).
+//   - `suins = { r.mvr = "@suins/core" }`  ->  a LOCAL copy with `Published.toml`/
+//     `Move.lock` stripped (MVR doesn't resolve on localnet; and although this suins
+//     rev ships no `Published.toml`, its committed `Move.lock` carries `[env]`
+//     published-ids that the `-e testnet` build would otherwise link to instead of
+//     bundling — so it gets the same local-copy + strip treatment as sui_groups).
 //   - `sui_groups`  ->  a LOCAL copy with `Published.toml`/`Move.lock` stripped, so
 //     the `-e testnet` build treats it as unpublished and bundles it. devstack copies
 //     local deps into its build scratch; git deps would keep their published addresses.
@@ -62,12 +65,20 @@
 const PATCHED_MESSAGING = resolve(PATCHED_ROOT, 'sui_stack_messaging');
 const PATCHED_GROUPS = resolve(PATCHED_ROOT, 'sui_groups'); // git checkout root
 const PATCHED_GROUPS_PKG = resolve(PATCHED_GROUPS, 'move/packages/sui_groups');
+const PATCHED_SUINS = resolve(PATCHED_ROOT, 'suins'); // git checkout root
+const PATCHED_SUINS_PKG = resolve(PATCHED_SUINS, 'packages/suins');
 
 // Matches the `sui_groups` git rev pinned in the canonical messaging Move.toml.
 const SUI_GROUPS_GIT = 'https://github.com/MystenLabs/sui-groups.git';
 const SUI_GROUPS_REV = 'ea766818b90e162341e885a855718388edcc8e99';
-const SUINS_GIT_DEP =
-	'suins = { git = "https://github.com/MystenLabs/suins-contracts", subdir = "packages/suins", rev = "2b75990bdc31472405a6bf47b40152627a1fa6c0" }';
+// suins ships no Published.toml at this rev, but its committed Move.lock carries
+// `[env]` published-ids (testnet 0x40eee27b…). As a git dep those leak through and
+// the `-e testnet` build LINKS to that id instead of bundling — and it isn't on
+// localnet. So materialize a LOCAL copy with Published.toml/Move.lock stripped,
+// same as sui_groups, so the build treats suins as unpublished and bundles it.
+const SUINS_GIT = 'https://github.com/MystenLabs/suins-contracts.git';
+const SUINS_REV = '2b75990bdc31472405a6bf47b40152627a1fa6c0';
+const SUINS_DEP = 'suins = { local = "../suins/packages/suins" }';
 
 // Strip committed published addresses + lockfile so the `-e testnet` build treats a
 // package as UNPUBLISHED on localnet and bundles it.
@@ -87,6 +98,17 @@
 	stripPublished(PATCHED_GROUPS_PKG);
 }
 
+function materializeSuins() {
+	if (!existsSync(resolve(PATCHED_SUINS_PKG, 'Move.toml'))) {
+		rmSync(PATCHED_SUINS, { recursive: true, force: true });
+		execFileSync('git', ['clone', '--quiet', SUINS_GIT, PATCHED_SUINS], { stdio: 'inherit' });
+		execFileSync('git', ['-C', PATCHED_SUINS, 'checkout', '--quiet', SUINS_REV], {
+			stdio: 'inherit',
+		});
+	}
+	stripPublished(PATCHED_SUINS_PKG);
+}
+
 function materializeMessaging() {
 	rmSync(PATCHED_MESSAGING, { recursive: true, force: true });
 	cpSync(CANONICAL_MESSAGING, PATCHED_MESSAGING, {
@@ -96,7 +118,7 @@
 	});
 	const tomlPath = resolve(PATCHED_MESSAGING, 'Move.toml');
 	const toml = readFileSync(tomlPath, 'utf8')
-		.replace('suins = { r.mvr = "@suins/core" }', SUINS_GIT_DEP)
+		.replace('suins = { r.mvr = "@suins/core" }', SUINS_DEP)
 		.replace(
 			/^sui_groups = \{ git =.*$/m,
 			'sui_groups = { local = "../sui_groups/move/packages/sui_groups" }',
@@ -106,6 +128,7 @@
 }
 
 materializeSuiGroups();
+materializeSuins();
 materializeMessaging();
 
 // --- Network + accounts -----------------------------------------------------


## Walrus (optional)

Only message **attachments** need Walrus; messaging and decryption don't. Add `walrus({ local: {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically correct but kind of defeats the whole purpose?
Should we also include a local walrus instance via the devstack?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fully agreed.
Opened SEW-1004 to track this.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fully agree. Opened SEW-1004 to track this.

Comment thread chat-app/src/lib/devstack-config.ts Outdated
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>
@ioannischtz ioannischtz merged commit f3bb146 into main Jun 10, 2026
8 checks passed
@ioannischtz ioannischtz deleted the devstack-localnet branch June 10, 2026 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants