Skip to content

Promote dev → staging - #1122

Merged
ducnmm merged 5 commits into
stagingfrom
dev
Oct 6, 2026
Merged

ducnmm merged 5 commits into
stagingfrom
dev

Conversation

@ducnmm

@ducnmm ducnmm commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Promotes dev into staging: 5 commits since 1ee78011. This carries the Sept 2026 dashboard (#1006), the WALM-687 credential redaction (#996), and the prepared-upload wallet fix (#1078).

Changes

App — Sept 2026 dashboard (#1006)

  • Restyles the signed-in dashboard, sign-in page, playground, MCP connect screens, and admin to the Sept 2026 design.
  • Replaces the sign-in phone with the laptop screen and the purple bloom behind it. On a window shorter than a 14-inch display, the stage scales to the full width so the laptop meets the right edge.
  • Adds the admin activity API (daily memories, and hourly bars for a 24h window), click-to-copy addresses, and the memory_tombstones (deleted_at) index.
  • Keeps delegate keys, namespaces, and the playground. The Walrus Console promo stays off unless VITE_WALRUS_CONSOLE_ENABLED is true, and the Docker build now receives the console and legal URLs.
  • Analytics: Statsig receives the funnel, the client script is pinned by SRI, nothing initialises on /admin, and 64-hex chain ids are redacted again.

MCP — WALM-687 (#996)

  • Redacts credentials that are split across memwal_analyze lines.
  • Screens bare tokens against neighbouring lines, so one credential label in a long transcript does not drop distant blob ids.

Relayer — prepared upload wallet (#1078)

  • Pins a prepared upload to the wallet already recorded on its journal. WALLET_MAPPING_MISMATCH stops the job instead of burning the remaining attempts.
  • Drops a stale encoded checkpoint when an unpaid analyze retry re-encrypts the fact, so the resume does not keep the previous blob id.
  • Retries a cached Walrus object miss on a registered upload, and refreshes the Walrus price after destroy_zero on a register.

Test plan

ducnmm and others added 4 commits September 23, 2026 09:59
Passage mode was screening bare tokens against the whole batch, so one
credential label in a long transcript falsely dropped distant blob ids /
SHAs. Add bareScope (default batch) and call with neighbours from
sanitizePassage after omitting blank lines so blank-separated label+seed
still redacts. Regression tests cover both cases.
…al_analyze-stores-a-credential-split-across-lines-gh

fix(mcp): redact credentials split across analyze lines (WALM-687)
* feat(app): restyle the dashboard to the Sept 2026 design

Keep delegate keys, namespaces, and the playground, and hide the Walrus Console promo until its calendar date. Console links open console.wal.app, Claude Code install commands match the docs, and pasting a delegate key checks the current account on chain.

* fix(app): point the Walrus Console promo at console.walrus.xyz

The date gate is unchanged. The links were opening the wrong host.

* fix(app): toggle the Walrus Console promo with a boolean flag

Replace the calendar-date gate with VITE_WALRUS_CONSOLE_ENABLED. The promo stays off unless that value is true.

* feat(app): restyle the MCP connect screens to match the dashboard

Use the same dark column, type, and flat cards for the local MCP login and the Claude consent page. The sign-in steps are unchanged.

* fix(app): keep the playground open when this browser has no key

Stop sending /playground back to the dashboard. Show the same yellow notice with a paste field, and leave Run disabled until a registered delegate key is attached.

* fix(app): keep the playground key notice above the steps

The shared dashboard alert order was pushing the yellow notice to the bottom of the playground.

* fix(app): finish the playground key gate and MCP consent screen

Keep the playground open without a key, and restyle the MCP consent page to the same type as the dashboard. Details stay collapsed until opened.

* fix(app): open the playground at the top and drop shouted labels

Scrolling from the dashboard no longer lands midway down the playground. Buttons and links keep the wording as written instead of full capitals.

* fix(app): restore uppercase labels, including the MCP approve button

The sentence-case pass was a mistake. Dashboard, playground, and the MCP consent button use the tracked capitals again.

* fix(app): bake the Walrus Console flag into the Docker build

Railway already sets VITE_WALRUS_CONSOLE_ENABLED, but the image never received it, so the promo stayed off.

* fix(app): align the console button with the install steps

Put the Walrus Console link in the same column as the step text, and open up the space between the agent steps.

* fix(app): apply the dashboard design review notes

Keep the install connector on the first tab, show the SDK quickstart in the app step, and drop the AI SDK block. Tighten mobile key rows, selection, and the paste-key form.

* fix(app): space the connect cards and center the Codex tab icon

Give the subtitle more room above the two connect modules, and keep the Codex mark centered in its tab.

* feat(app): restyle the sign-in page and finish the dashboard review

Keep the signed-in dashboard and the signed-out sign-in page on one branch. The playground stops after the basic health, remember, and recall steps.

* feat(admin): chart memories by day and match the dashboard

Add the admin activity API with a 30-day window, keep balance samples
long enough for that comparison, and restyle admin plus the sign-in
stage to the Sept 2026 layout.

* feat(app): send the funnel to Statsig with key join ids

Forward trackEvent and page views to Statsig, and attach the delegate
public key plus transaction digest on the two successful key events so
the visit can be joined to on-chain activity.

* fix(docs): exempt the admin activity route from the public reference

The freshness check already leaves the other ADMIN_API_KEY routes
undocumented. /api/admin/activity belongs in that same list.

* fix(app): lower the sign-in layout and match the glass tiles

Shift the desktop and mobile content down with the phone, and fill the
sign-in buttons white on hover. The right tile is more transparent and
the left tile keeps a darker frost.

* fix(app): drop the extra background under playground results

The result text was sitting in a second gray box inside the yellow
frame. Keep the frame and let the JSON sit directly in it.

* fix(app): restyle the dashboard confirm dialogs

Match the remove-key, delete-memory, and preview dialogs to the
dashboard: black panel, Ratch title, and outline pills.

* fix(app): use David's mascot-free Open Graph image

Point the social preview at the 1200x630 wordmark image and keep the
old filename serving the same file so existing links do not 404.

* fix(app): replace the sign-in phone with the laptop graphic

David's updated sign-in visual uses the dashboard on a laptop instead of a phone. The glass tiles follow that screen, and the top mobile tile sits behind it.

* fix(app): enlarge the mobile sign-in laptop and its tiles

Give the laptop and glass tiles a little more size, and open up the space above and below them.

* fix(app): use the final page title and meta description

Kenton confirmed the title and description, including the Open Graph and Twitter tags.

* feat(admin): hourly memory chart, click-to-copy addresses, fuller error details

Memories written: a 24h window has one calendar day, so the daily chart
drew a single bar across the whole card. For windows of 24h or less the
activity route now also returns memories_by_hour (same viewer-offset
bucketing as the daily query, hours with no jobs filled with zero, absent
for longer windows so existing clients are unaffected), and the chart draws
one bar per hour. Midnight ticks show the date, and tooltips and the
summary name the date and hour.

Addresses: the upload-errors table showed only the first six characters
(0x07e5). Every admin address (upload errors, top owners, uploader pool,
sponsor wallet) now reads 0x5c3a...907e and copies the full value when
clicked. A copy icon appears on hover; on click the text turns green, the
icon pops to a check and a "Copied" chip rises and fades (red "Copy failed"
if the clipboard is refused). The row copy button used to give no feedback
at all, since its copied state was only wired to the modal.

Error details: the modal showed a timestamp and the message. It now shows
the job ID, full owner (copy, and a Suiscan link for the deployment's
network), namespace, status, queued and failed times with the gap between
them, the message with its own copy, a clear note when the server recorded
none, and "Copy all details" as JSON for a ticket. The server already sent
status and created_at; the client dropped them. The content area also
scrolls now on short screens instead of being cut off.

Rust: 2 new unit tests for hourly buckets (positive and negative offsets,
empty window); admin_activity 10/10. App: tsc clean, vitest 112/112.

* perf(server): index memory_tombstones by deleted_at for admin activity

/api/admin/activity counts tombstones in a deleted_at window with no owner,
for the current and the previous window. The only index is
(owner, deleted_at, memory_id), which cannot serve that range, so each call
scanned the table twice, and the admin view polls every 60s per open tab.

Adds 024 with CREATE INDEX CONCURRENTLY in its own file (as 016/018/022)
and registers it in CONCURRENTLY_BUILT_INDEXES so an interrupted build is
recovered. storage::db tests 19/19, including the wiring and registry
checks.

* fix(app): keep chain ids out of analytics and redact every 64-hex value

7c9dd91 exempted delegate_public_key and transaction_digest from the
redaction rules and sent both on delegate_key_register_complete and
delegate_key_add_complete to GA/GTM, PostHog and Statsig.

- A transaction digest resolves on-chain to the sender's wallet, so every
  analytics profile (PostHog id, Statsig stableID) became linkable to an
  address, which the existing redaction policy exists to prevent.
- The exemption was keyed by property name, so a real 64-hex private key
  passed as delegate_public_key was sent unredacted. The old test only
  used a 63-character value, so it did not catch this.

Both fields are removed from the two events and the exemptions are gone:
a 64-hex value is redacted under any property name again. The events,
page views and the Statsig sink are otherwise unchanged. If joining the
funnel to chain activity is still wanted, it needs a privacy sign-off and
an id that is not derivable from public chain data.

Tests: 64-hex redacted under public-key names; the two key events no
longer carry either field. vitest 122/122, tsc -b clean.

* fix(app): pin the Statsig script by SRI and keep analytics off /admin

The Statsig client is loaded from jsDelivr with no integrity attribute and
there is no CSP, while the same origin keeps the delegate private key and
the admin API key in sessionStorage. A changed CDN response would run with
access to both.

- The script tag now carries sha384 integrity for exactly
  @statsig/js-client@3.33.5/build/statsig-js-client.min.js. The hash was
  computed locally and matches jsDelivr's published hash for that file
  (the file is served immutable). In a browser, the correct hash loads and
  a tampered one is blocked.
- No third-party analytics (GTM, PostHog, Statsig) initialises or sends on
  /admin, which holds the admin key and has nothing to measure.

A CSP for the whole app is still worth adding, but it touches GTM, PostHog
and wallet popups, so it is left out of this PR.

vitest 124/124, tsc -b clean.

* fix(app): clear a pasted delegate key once it is imported

After "Use this key" succeeded on the dashboard, the pasted private key
stayed in plain text in the textarea: its state lives in
ConnectWalrusMemory and nothing cleared it (the Playground version does).

- importExistingKey now resolves true once the key is stored, and the form
  clears the field then. A failed import keeps the value so a typo can be
  fixed.
- The field is masked like a password, has autocomplete, autocorrect and
  autocapitalize off, and carries data-analytics-redact so the click guard
  treats it as sensitive.

Test: the field keeps the key after a failed import and is empty after a
successful one. vitest 125/125, tsc -b clean.

* fix(app): pin the desktop sign-in laptop to the right edge

A wide window letterboxed the device away from the corner. The wordmark follows the stage.

* fix(app): match the Back to Console dialog's top padding to its sides

The title sat tighter against the top edge than the left and right padding.

* fix(app): center the sign-in hero above a 14-inch width

The laptop stays on the right edge through 1512px. Wider windows center the group, and the wordmark lines up with the title.

* fix(app): put the sign-in wordmark back in the frame's top left

The logo sits 50px from the frame edge, left of the Sign in column, as in the design.

* feat(app): animate the dashboard copy buttons

Copy icons crossfade to a drawn check (or a cross on failure), the wallet
address blurs to Copied at a locked width, and the button presses 1px.
Copies fall back to execCommand, report failures, and announce the result
to screen readers. Motion is CSS-only and off under reduced motion.

* fix(app): lay the signed-in pages out for phones

Under 640px the Connect Walrus Memory timeline starts flush left on a
48px rail instead of hanging off the first tab, commands scroll sideways
instead of breaking mid-word, and the playground title fits. Under 480px
the client icons sit above the card title. Under 420px Sign out collapses
to its icon so the address no longer runs into the logo.

* fix(app): pass VITE_CONSOLE_URL and the legal URLs into the Docker build (#1113)

The Dockerfile had no ARG for them, so the Railway values never reached
Vite and the Back to Console dialog was compiled out on every deploy.

* fix(app): bake the current Console and deployment defaults

The Walrus Site build never received the console and legal URLs, and
the image still fell back to the pre-cutover packages. Defaults now
match the live Railway deployments, and an unset Console URL points at
that network's Memory tab.

* fix(app): center the sign-in hero on a short 14-inch window

A 14-inch MacBook at 100% zoom is shorter than the Figma frame, so
pinning the stage right left a wide gap on the left. Center that
window. Keep the laptop on the right edge only while the window is
at least as tall as a 14-inch fullscreen.

* fix(app): grow a short sign-in window until the laptop meets the right edge

Use the updated laptop screen and the purple bloom behind it. On a window
shorter than a 14-inch display, scale the stage to the full width so the
laptop touches the right edge.

---------

Co-authored-by: Harry Phan <phanhoangvinhhien@gmail.com>
Co-authored-by: Nikola Le <91601109+nikola0x0@users.noreply.github.com>
…ncoded resume (#1078)

* fix(server): keep a prepared upload on its journaled wallet

A normal retry treated an encoded journal that already named a signer as
free to steer. The next slot still sent the old wallet address, the sidecar
returned WALLET_MAPPING_MISMATCH, and the job burned all five attempts.

Pin the signer once the journal has a wallet address or a prepared register.
An encoded checkpoint with no signer can still move. Classify
WALLET_MAPPING_MISMATCH as permanent so a real key-slot change stops
instead of retrying the same journal.

* fix(server): drop a stale encoded checkpoint when analyze retries

An unpaid analyze retry re-encrypts the fact. The old encoded resume still
names the previous blob id, so Walrus rejects the new bytes as a resume
blobId mismatch and the job burns five attempts.

Clear that checkpoint when the unpaid row is reset. If a retry still hits
the mismatch, drop the encoded resume and encode the current bytes. A
resume past encode stays in place.

* fix(sidecar): retry a cached Walrus object miss on registered upload

A registered resume calls getBlobObject. The Walrus DataLoader keeps that
Error, so the next attempt fails in a few milliseconds and the job burns
five tries while the blob is already on chain.

Retry the miss on the existing effects schedule and reset that client
before the next read, including when the schedule is exhausted. Effects
lag still retries without clearing the committee cache. The registered
journal stays in place.

* fix(sidecar): refresh the Walrus price after a register destroy_zero

The durable upload route only rebuilt the Walrus client on the 60s max-age
timer. A stale storage price then failed Enoki's sponsor dry-run with
0x2::balance::destroy_zero on every retry inside that window. Refresh on
that abort, the same way the legacy upload route already does, so the next
attempt registers against the live price.
@ducnmm
ducnmm merged commit df7b9c6 into staging Oct 6, 2026
43 of 44 checks passed
@ducnmm ducnmm mentioned this pull request Oct 6, 2026
3 tasks

This branch had an error being deployed

1 failed and 1 active deployments
benchmark-dev — 3e0534e6 Deployed Oct 6, 2026 by ducnmm via Memory API Latency #400
Walrus Memory / dev — 3e0534e6 Deployed Oct 6, 2026 by railway-app[bot]
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