chore: align dev with staging baseline (docs + seal_approve security fix) - #508
Open
harrymove-ctrl wants to merge 89 commits into
Open
chore: align dev with staging baseline (docs + seal_approve security fix)#508harrymove-ctrl wants to merge 89 commits into
harrymove-ctrl wants to merge 89 commits into
Conversation
…as coins" useSponsoredTransaction no longer falls back to direct self-pay when the Enoki sponsor step fails. On a gasless zkLogin wallet (0 SUI) that fallback always aborted in the Sui SDK gas resolver with "No valid gas coins found for the transaction.", masking the real cause (network blip, relayer 429/5xx, sponsor dry-run rejection). Now every user — zkLogin and regular wallet — is gaslessly sponsored: retry the sponsor flow on transient failures (429/500/503/504/408 + network) with backoff, and surface the real reason otherwise. 502 (Enoki dry-run rejection, e.g. duplicate delegate key) fails fast. Public API unchanged.
…N-RPC sunset 2026-07-31)
For dev/testnet validation only. Config-gated and OFF by default (SUI_GRPC_URL
empty -> unchanged JSON-RPC behaviour), so this is a no-op until the env is set.
- config.ts: add SUI_GRPC_URL.
- clients.ts: shared write-path suiClient (Walrus/SEAL/Enoki build+certify) uses
SuiGrpcClient when SUI_GRPC_URL is set, else JSON-RPC. Keep a dedicated
suiJsonRpcClient for the query/restore path (getOwnedObjects /
getDynamicFieldObject / suix_queryTransactionBlocks are JSON-RPC-only).
getSuiBalanceMist now reads both {totalBalance} (JSON-RPC) and
{balance:{balance}} (gRPC) shapes — found via live smoke test.
- walrus-query.ts: route index-method reads through suiJsonRpcClient.
NOT validated e2e: full Walrus register/certify/get_blob + Enoki tx.build + SEAL
decrypt over gRPC need a live relayer — that is what this dev deploy tests.
Query path + Rust side JSON-RPC are stage 2.
Under the gRPC client the Walrus certify upload failed at certify_sponsor with 'Transaction was not signed by the correct sender ... given owner/signer 0x0': the SDK's certify tx is built without a sender (register sets its own via setSenderIfNotSet, certify does not), and the gRPC client validates owned-object inputs against the tx sender during build/resolution. Set the sender in the Enoki sponsor path before tx.build; Enoki still sponsors with its own sender and onlyTransactionKind excludes the sender from the bytes, so this is resolution-only and a no-op on JSON-RPC. Surfaced by the dev testnet gRPC relayer test.
…371) Require the requested key id to be namespaced to the account owner on both the owner and delegate paths (the owner returns early). This binds `id` to the passed `account`, so a delegate is only ever authorized for the data of the account it is registered on. Adds a regression test asserting a delegate is denied an id scoped to an unrelated owner (aborts ENoAccess). 48/48 tests pass. Code-only change; not deployed.
Two bugs found while verifying PR #355's SUI_GRPC_URL write path: - enoki.ts direct-sign fallback read `direct.digest` assuming SuiJsonRpcClient's flat SuiTransactionBlockResponse shape. Under SuiGrpcClient, signAndExecuteTransaction resolves to the core-API union `{Transaction: {digest}} | {FailedTransaction: {digest}}` with no top-level `.digest`, so this silently returned undefined once SUI_GRPC_URL was set. Added extractTransactionDigest() to handle both shapes explicitly. - retry/rpc.ts's isRetryableRpcError only matched JSON-RPC-style error text ("429", "503", "timeout"). gRPC errors from SuiGrpcClient carry a status code (RpcError.code) instead, so transient gRPC failures (UNAVAILABLE, RESOURCE_EXHAUSTED, DEADLINE_EXCEEDED, ABORTED) were not retried on the write path. Added a code-based check alongside the existing string matching. Verified both fixes locally: sidecar boots clean on JSON-RPC and gRPC (real mainnet fullnode), getSuiBalanceMist resolves identically on both, and a simulated gRPC transient error now retries and recovers.
Not part of PR #355's own diff (services/server/scripts/sidecar/*) — these are pre-existing bugs in apps/app surfaced only because testnet's public JSON-RPC endpoint is returning HTTP 404 right now (confirmed live), ahead of the documented 2026-07-31 sunset. @mysten/dapp-kit's SuiClientProvider defaults every network to JSON-RPC, so every useSuiClient() consumer broke identically once exercised against testnet. - App.tsx: SuiClientProvider now uses a SuiGrpcClient for testnet via the createClient override (mainnet untouched, still JSON-RPC-healthy). - SetupWizard.tsx / Dashboard.tsx: account/delegate-key lookups used JSON-RPC-shaped getObject/getDynamicFieldObject calls (RpcError: INVALID_ARGUMENT under gRPC). Rewritten for gRPC's flatter .json shape and base64-encoded public_key (both verified live against real testnet objects, not guessed from docs). - useSponsoredTransaction.ts: the direct-sign fallback reused the same Transaction object already .build()'d with onlyTransactionKind:true (no sender attached), causing wrong-sender execution (ENotOwner on-chain, reproduced across two different wallets). Now rebuilds via Transaction.fromKind(). Also added an execute() override since dapp-kit's default calls the JSON-RPC-only client.executeTransactionBlock(), which doesn't exist on SuiGrpcClient (core API only has executeTransaction(), different response shape). - vite.config.ts: dev-only proxy for /api, /health, /version, /config, /sponsor to the real dev backend — its CORS allowlist has no localhost entry, so local testing needs a same-origin proxy (no path rewrite, so signed-request signatures stay valid).
Real, live incident: testnet's public JSON-RPC endpoint (fullnode.testnet.sui.io) already returns HTTP 404 today, ahead of the documented 2026-07-31 sunset. verify_delegate_key_onchain (storage/sui.rs) called this endpoint directly via raw sui_getObject JSON-RPC for every signed request's account resolution. Any failure there — including a dead endpoint — gets mapped to a uniform 401 by auth.rs's constant_time_reject() (deliberate: prevents timing oracles between "wrong key" and "account not found"), so the real cause was indistinguishable from bad credentials. In practice this means relayer.dev.memwal.ai currently cannot authenticate any signed request on testnet, regardless of whether the caller's account/delegate key is correct. This is the same JSON-RPC sunset PR #355 addresses for the sidecar's Walrus write path — just in the Rust backend's auth path, which #355 didn't touch. - Config: add SUI_GRPC_URL (opt-in, mirrors the sidecar/web-app pattern — empty keeps the existing JSON-RPC behavior unchanged). - storage/sui.rs: verify_delegate_key_onchain now branches to a gRPC implementation (LedgerService.GetObject via the sui-rpc crate) when SUI_GRPC_URL is set. gRPC's object.json representation is flatter than JSON-RPC's parsed .fields shape and encodes delegate key public_key as base64 (not a byte array) — verified against real, live testnet objects with a real registered delegate key (not guessed from docs, which for this crate were largely unhelpful — see the two live #[ignore] tests). - find_account_by_delegate_key (registry-scan fallback, used only when the caller sends no x-account-id hint) stays JSON-RPC-only: gRPC has no single-key dynamic-field lookup, only paginated ListDynamicFields, and modern SDKs always send the account-id hint, which resolve_account's Strategy 2 checks first — that's the path this fix actually needed to cover for the live incident. Verified: cargo check clean, cargo clippy clean (no new warnings), full test suite passes (294/299 — the 5 failures are pre-existing, unrelated jobs.rs tests needing a local Postgres connection, not present in this environment). The two new #[ignore] tests hit real testnet gRPC and pass.
Code review of the prior frontend fix (e89788c) found it introduced a real regression: SetupWizard.tsx and Dashboard.tsx were rewritten to call gRPC's getObject/getDynamicField shapes unconditionally, but App.tsx's createClientForNetwork only swaps testnet to SuiGrpcClient — mainnet still gets SuiJsonRpcClient. Those two files would have broken on mainnet (wrong getObject params, and getDynamicField doesn't exist on SuiJsonRpcClient at all). Separately, ConnectMcp.tsx was missed entirely and still used the original JSON-RPC-only shape, breaking on testnet (the default network) — the exact bug class this whole fix line was meant to close, just in a fourth file nobody looked at. Replaced all three call sites with shared helpers in the new utils/suiClientCompat.ts that duck-type the client (`typeof client.getDynamicField === 'function'`) and branch accordingly, instead of assuming one transport. fetchObjectJson's JSON-RPC branch recursively unwraps Move's {fields: {...}} struct envelopes so both transports return the same flat shape to callers — matches gRPC's .json representation at every nesting level, not just the top one. publicKeyToHex handles both delegate-key encodings (JSON-RPC's number[], gRPC's base64 string). Verified: tsc --noEmit clean, dev server HMR-reloaded all three files with no runtime errors.
Both were explicitly marked "TEMPORARY LOCAL PATCH (not for upstream)" — resolving that before this could reasonably be considered for merge. - config.ts / App.tsx: VITE_SUI_GRPC_URL (opt-in, empty keeps JSON-RPC unchanged) replaces the hardcoded testnet-only fullnode URL. createClientForNetwork now applies to whichever network is actually configured (config.suiNetwork), not a hardcoded 'testnet' string. - vite.config.ts: DEV_BACKEND_PROXY_TARGET (opt-in, unset by default — no proxy configured, matching upstream's actual behavior) replaces the hardcoded relayer.dev.memwal.ai target. Uses loadEnv() since vite.config.ts needs .env.local values in its own Node-side execution, not just the client bundle. Verified: tsc --noEmit clean, dev server boots clean with the new env-driven config (.env.local updated to set VITE_SUI_GRPC_URL explicitly).
Four parallel cleanup reviews (reuse, simplification, efficiency, altitude) over the fix commits; net -21 lines. Fixes applied: - [efficiency, HIGH] services/server: sui_rpc::Client was constructed on every auth verification — sui_rpc's Client::new parses the OS root-cert store and opens a fresh TLS channel per call, on the per-request auth hot path, the opposite of how the JSON-RPC path reuses the pooled reqwest::Client. Now built once at startup into AppState (fails fast on a bad SUI_GRPC_URL) and cloned per request — clones share the tonic channel. Both live testnet gRPC tests still pass against the refactored path. - [efficiency] suiClientCompat.fetchAccountIdForOwner: the registry's inner Table ID is an immutable on-chain constant but was re-fetched on every account lookup — now memoized per registryId, halving round trips on repeat lookups. - [reuse] suiClientCompat: dropped all hand-rolled hex/base64 encoders for toHex/fromHex/fromBase64/normalizeSuiAddress from @mysten/sui/utils (already a dependency). - [reuse+altitude] useSponsoredTransaction: executeTransactionCompat moved into suiClientCompat next to the other transport-compat helpers, so the app has one shared isGrpcClient discriminator instead of two divergent method-presence heuristics in two files, and one base64 decode instead of a second inline atob copy. - [simplification] deleted apps/app/src/utils/suiFields.ts — dead after the compat refactor removed its last importer, and its typed shapes had already drifted from the real on-chain encodings (public_key: number[] only, while gRPC returns base64 strings). - [review nits] fixed the stale "testnet-only" header comment in suiClientCompat; publicKeyToHex now warns on an unrecognized encoding instead of silently returning ''. Skipped (reviewed, deliberately not changed): macro-consolidating the four 3-line grpc_value_as_* accessors (idiomatic as-is); a transport trait for verify_delegate_key_onchain (no such convention in storage/*, and the registry-scan fallback genuinely needs per-call-site transport choice); page-local bytesToHex/hexToBytes copies still in live use for key derivation (pre-existing, out of diff scope). Verified: cargo check --tests clean, clippy no new warnings, live gRPC tests pass, tsc --noEmit clean, dev server HMR-reloads without errors.
… has 1.88)
Railway build failure: sui-sdk-types (transitive via sui-rpc) pulled in
roaring 0.11.4, which requires rustc >=1.90.0. The Dockerfile pins
rust:1.88-bookworm, so the build failed at `cargo build --release` before
reaching any of our own code:
error: rustc 1.88.0 is not supported by the following package:
roaring@0.11.4 requires rustc 1.90.0
0.11.3 requires rustc 1.82.0 (compatible) and is otherwise identical for our
purposes (roaring is a transitive dep neither our code nor sui-rpc/
sui-sdk-types code paths we hit exercise directly).
Not verifiable via local `docker build` on this machine: the pinned
linux/amd64 base image is emulated via QEMU on Apple Silicon, and QEMU
itself segfaults on rustc invocation before any dependency compiles
(pre-existing environment issue, unrelated to this fix — same crash occurs
on the pre-fix Cargo.lock too). `cargo update -p roaring --precise 0.11.3`
+ `cargo check` locally (rustc 1.92) confirms the resolution is valid; the
actual rustc-1.88 constraint can only be verified by Railway's real amd64
build.
Dockerfile only declared ARG/ENV for a fixed list of VITE_ vars, so Railway's VITE_SUI_GRPC_URL service variable never reached the Vite build — the bundle always baked in an empty value and silently fell back to the dead JSON-RPC client.
…ontent docs: remove Seal encryption claims from Walrus Memory overview
The restore path still called suix_queryTransactionBlocks and getDynamicFieldObject over JSON-RPC, which testnet no longer serves — POST /api/restore 500'd with 'returned non-JSON (404)'. The stage-2 GraphQL note is obsolete: the current SDK's gRPC client covers this with listOwnedObjects (server-side type filter + json content) and getDynamicField. With SUI_GRPC_URL set, one paginated listOwnedObjects call replaces both the transaction scan and multiGetObjects, and blob metadata is BCS-decoded from getDynamicField (Metadata = VecMap<String,String>). Unset, the original JSON-RPC path still runs — same reversible opt-in as the write path. Verified against live testnet gRPC: real account returns all blobs with correct memwal_* metadata; namespace filtering, full-scan and empty-owner paths OK; 78/78 unit tests pass.
feat(relayer): gRPC write path for the JSON-RPC sunset (2026-07-31)
Resolve conflict in useSponsoredTransaction.ts: keep the no-fallback retry version. dev's changes to this file (executeTransactionCompat wiring and the Transaction.fromKind fallback rebuild from the gRPC migration) only served the self-pay fallback path this PR deletes, so they are dropped along with the now-dead executeTransactionCompat helper and its stale App.tsx comment reference.
…llback fix(app): sponsor all txs, drop self-pay fallback masking "No valid gas coins"
…mories docs: add guide for deleting old memories
Remove the Guides tab (which only contained the delete-old-memories guide) from the docs navigation so the page is no longer surfaced in the site. The guide's markdown file is kept in place so the content is preserved and can be re-enabled by restoring the navigation entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4ARRUn69UZpxyvaFFUfuQ
…de-3hfo7a docs: hide delete-old-memories guide from navigation
Reverse of the navigation change that hid the Delete old memories guide: re-adds the Guides tab so the page is surfaced again. Also renames the "At risk" memory status to "Stored". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4ARRUn69UZpxyvaFFUfuQ
Add a new "Delete memories programmatically" guide covering the Security Delete API flow (challenge/verify auth, list deletable blobs, prepare sponsored deletion, submit signed transaction), and list it in the Guides tab alongside the dashboard guide. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4ARRUn69UZpxyvaFFUfuQ
Remove the sentence linking to /api/security-delete, which does not exist yet, to avoid a broken link. Keep the cross-link to the dashboard guide. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4ARRUn69UZpxyvaFFUfuQ
…guide-3hfo7a docs: restore delete-old-memories guide
Rename the SDK tab to "TypeScript SDK" (paralleling the Python SDK tab) and restructure its sidebar into a logical progression: intro -> get started -> usage -> advanced -> recipes -> examples -> reference. Surface the existing but previously unlisted pages (overview, advanced usage, @ai-sdk integration, example map, examples, research app example) and move reference material (API Reference, Changelog) to the end so the section reads top to bottom. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WTyNVbzD3xVivzLTARZNdY
…nxzl3 docs: reorder TypeScript SDK nav for better flow
the evolved security-delete feature and relayer hardening Both branches had diverged substantially (112 files, +18.7k/-1k lines) since dev's PR #355 gRPC migration landed without ever reaching staging, while staging independently rebuilt the delete-old-memories feature into "security_delete" (native Sui gRPC client in services/server/src/sui/, dedicated auth/error/store modules) and hardened the relayer (destroy_zero recovery, dedicated JSON-RPC RPC provider). This merge keeps both lines of work; base = staging (dev has no unique commits it kept since #389 was closed unmerged). Conflict resolutions (15 files): - App.tsx / config.ts / suiClientCompat.ts: kept staging's deliberate architecture — the shared SuiClientProvider stays on JSON-RPC (documented reason: every JSON-RPC-shaped consumer would need dual-transport compat otherwise), gRPC is scoped to the security-delete subsystem. Removed dev's now-dead top-level createClientForNetwork/gRPC swap and its unused imports. - Dockerfile: kept both VITE_SUI_RPC_URL (staging) and VITE_SUI_GRPC_URL (dev) ARG/ENV pairs. - vite.config.ts: kept staging's dev-only E2E wallet injector addition (dev didn't touch this file). - docs/guides/delete-old-memories.md: took dev's later wording fix ("Stored" status label) since it matches what SecurityDeleteSection.tsx actually renders; staging's "At risk" wording was stale. - services/server/{auth,main,storage/sui}.rs, types.rs: kept staging's side throughout — it added a real fix (validate_memwal_account_type, rejecting objects that aren't actually a MemWalAccount before trusting their fields) that dev's simpler verify_delegate_key_onchain lacks. types.rs keeps both doc comments (merged, not a pick). - Cargo.toml/.lock: kept staging's exact-pinned crate set (needed by the new sui/ native client module); lockfile regenerated via cargo build. - sidecar clients.ts/config.ts/routes/walrus-query.ts: kept staging's hardened testnet policy (SUI_GRPC_URL mandatory on testnet, boot-time validateSuiTransportPolicy guard, suiJsonRpcClient forced null on testnet) over dev's opt-in/lenient version. IMPORTANT — found during review, not introduced by this merge: staging's account.move currently lacks security fix 97754fc ("scope seal_approve authorization to the account owner", dev-only, marked "code-only; not deployed" at the time). Without it, a registered delegate's seal_approve authorization does not bind the requested key `id` to the account they're a delegate on, so `is_delegate_address` alone can satisfy the assert regardless of whose data the id belongs to. This merge's Move source now has dev's fix (git auto-merged it cleanly since staging never touched this function), plus its regression test (test_seal_approve_delegate_rejects_unrelated_id, previously absent from staging). Needs a decision on whether/where this contract change has already been published on-chain. Verified after resolution: cargo check clean; cargo test 273/278 (5 failures are pre-existing local DB-pool timeouts, unrelated); sidecar 89/89; app tsc + vite build + 66/66 vitest; Move contract 48/48.
…ontend The environment variables page only documented the self-hosted relayer, so developers integrating the client SDK or MCP server had no reference for the MEMWAL_* names the examples use. This adds Client SDK, MCP server, and frontend app sections, clarifies that the SDK reads a config object rather than env vars automatically, and notes that MEMWAL_PRIVATE_KEY and MEMWAL_KEY are the same delegate key. Fixes BEDU-775
…ly steps Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoBWxqLzd9hAxrhoqv3iSv
…IONS route Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoBWxqLzd9hAxrhoqv3iSv
The iframe title and figcaption claimed only ciphertext ever reaches the relayer. In the default relayer-backed flow the relayer receives plaintext and encrypts with Seal server-side; only the manual client flow keeps plaintext off the relayer. The figure text now states where plaintext lives per deployment mode, matching the rest of the page. Also strips trailing whitespace flagged by git diff --check in the diagram bundle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoBWxqLzd9hAxrhoqv3iSv
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoBWxqLzd9hAxrhoqv3iSv
…e export The redrawn diagram places encryption per deployment mode as the security review requested: plaintext enters managed and self-hosted relayers with encryption inside that boundary, TEE shows plaintext only inside the attested enclave, and only the manual client flow sends ciphertext to the relayer. Also fixes the bundle's internal page title. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoBWxqLzd9hAxrhoqv3iSv
Add structured frontmatter (title, description, keywords, goal, questions, answer) to all 78 docs pages for improved AI search visibility and citation, matching the format used in walrus PR #3579. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add goal/questions/answer frontmatter to how-agent-memory-works.md and where-to-store-agent-data.md. Correct min_words on 22 pages whose body is under 300 words so the validation contract matches reality. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrote all goal.description fields to be specific, action-oriented, and outcome-focused. Each description now names the concrete outcome the reader should be able to accomplish after reading the page, rather than restating the page title with 'Understand ...'. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Quote goal.description values containing colons to prevent YAML
parse errors. Convert HTML comment in troubleshooting/overview.md
to MDX syntax ({/* */}).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ages docs: add standardized frontmatter to all docs pages
…ust-boundary # Conflicts: # docs/fundamentals/architecture/data-flow-security-model.md
…s-docs-ctas-example-pages # Conflicts: # docs/examples/example-apps.md # docs/getting-started/quick-start.md # docs/getting-started/what-is-memwal.md
…c-02-walrus-memory-ui-relayer-api-contracts-endpoints # Conflicts: # docs/relayer/api-reference.md # docs/relayer/self-hosting.md
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoBWxqLzd9hAxrhoqv3iSv
The questions frontmatter mimics user search queries, where "How do I" is the house style; the second-person rule applies to page prose, not to these entries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoBWxqLzd9hAxrhoqv3iSv
…ndary BEDU-913: Walrus Memory trust boundary interactive diagram
…ctas-example-pages docs: add star CTAs and per-app example pages (BEDU-952, BEDU-953)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoBWxqLzd9hAxrhoqv3iSv
The questions frontmatter mimics user search queries, where "How do I" is the house style (per review on #490); the second-person rule applies to page prose only. Restores the five entries a style pass over-corrected before #488 and #498 merged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoBWxqLzd9hAxrhoqv3iSv
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoBWxqLzd9hAxrhoqv3iSv
…lrus-memory-ui-relayer-api-contracts-endpoints
chore: align dev with current staging (gRPC migration + docs merged into staging's security-delete work)
Align dev with the staging baseline: restore the app/server misc-fix files and the contract seal_approve change to staging's versions, so dev differs from staging by documentation only.
c2d102c ("chore: revert non-docs deltas to staging versions") reverted services/contract/sources/account.move and account_tests.move to staging's version along with the unrelated app/server files, but staging's version still has the seal_approve delegate-branch id-binding bug (GH #369 / WALM-165, Security/Critical): the delegate path never checks that the requested SEAL key id is namespaced to the account's owner, allowing cross-account SEAL decryption. dev's version fixes this by applying the id-binding check to both the owner and delegate paths. Restore both files to dev's fixed content. No other files touched.
Collaborator
Style Guide AuditAll 83 file(s) pass the style guide audit. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Scoped per Henry's stated policy: dev should differ from staging only by docs + smart contract, nothing else.
90 files changed: 88 docs + 2 contract. Zero app/server code changes.
dev— frontmatter standardization, new concept/guide pages, diagram updates.account.move+account_tests.move— restores theseal_approveid-binding fix (GH bug(contract): seal_approve delegate branch omits id binding, allowing cross-account SEAL decryption [Security / Critical] #369 / WALM-165, Security/Critical — cross-account SEAL decryption). This exists ondevbut not yet onstaging; kept intentionally as a real security fix, not scope creep. (An earlier commit on this branch reverted these two files to staging's vulnerable version along with the app/server files below — that was a mistake, corrected in a follow-up commit.)Explicitly excluded (reverted to staging's version, confirmed out of scope)
useSponsoredTransaction.ts,ConnectMcp.tsx,SetupWizard.tsx,suiClientCompat.ts,suiFields.ts,sidecar/retry/rpc.ts,types.rs— all unrelated app/server work (PR #353, PR #355) independent of this sync task.