Skip to content

Scaffold contextmem Move package (Move.toml, module stubs) + CI build/test + testnet publish #8

Open

Description

@harrymove-ctrl

Context

ContextMEM has zero Move code today — find for Move.toml/*.move returns nothing, and every "on-chain" touch is a read-only Sui query (packages/walrus/src/proof.ts uses SuiGrpcClient.getObject against Mysten's Walrus Sites package) or a third-party-signed write (Tatum, MemWal). This is the literal "where is my smart contract?" gap. Per roadmap §2, the answer is one minimal contextmem Move package (registry + receipt). This issue stands up the package skeleton and its CI so the two real modules (separate issues) have somewhere to live and a repeatable publish path.

Goal / user story

As a contributor, I can run sui move build / sui move test locally and in CI, and publish the package to Sui testnet with a single workflow run that records the resulting packageId, so downstream modules and the TS client have a stable on-chain address to target.

Acceptance criteria

  • New top-level move/contextmem/ package (sibling to packages/ and apps/) with Move.toml (edition 2024.beta, named address contextmem = "0x0", Sui framework dep pinned to a testnet rev) and a sources/ dir.
  • Compiling stub modules sources/registry.move and sources/receipt.move (empty module contextmem::registry {} / ::receipt {} is enough) plus a tests/ dir wired so sui move test runs green.
  • New CI workflow .github/workflows/move.yml that installs the Sui CLI and runs sui move build + sui move test on every PR touching move/** (the existing bun-check.yml is JS-only and must NOT be overloaded).
  • A workflow_dispatch (manual) job in the same workflow publishes to testnet using a SUI_TESTNET_PRIVATE_KEY repo secret + testnet faucet gas, and writes the published packageId to move/contextmem/published.testnet.json (uploaded as an artifact).
  • move/contextmem/README.md documents local build, the named-address/upgrade-cap conventions, and the signer/network decision (see notes).
  • Root package.json gains a move:build script (sui move build --path move/contextmem) so the toolchain is discoverable from the monorepo.

Implementation notes

  • Toolchain: pin a Sui CLI version in CI (download a MystenLabs/sui testnet release binary, or suiup); do NOT use cargo install (too slow). Cache the binary.
  • Network: publish to testnet to match what's already there — WALRUS_NETWORKS.testnet.sitePackage in packages/walrus/src/constants.ts and Harbor's testnet alpha. Roadmap decision docs: add product roadmap (Harbor storage + Talus on-chain direction) #4 (one network for the launch surface) means receipts and the blobs they cite must be co-located; testnet is the choice for the demo.
  • Publish gas: publish needs real testnet SUI from the faucet (Enoki sponsorship covers runtime txs, not the one-time publish). Have the workflow request faucet gas for the publish address before sui client publish --json.
  • Upgrade cap: capture the UpgradeCap object id alongside packageId in published.testnet.json so future module changes can be upgraded, not re-published to a new address.
  • DECISION to record in README (affects all sibling issues): signer + ownership. Runtime mints will be Enoki-sponsored (no SUI balance needed, mirroring Harbor's reserve→sign→finalize), but the sender/signer is the open question — recommended for alpha: a single backend service key (suiprivkey1..., decoded via Ed25519Keypair/decodeSuiPrivateKey) signs, Enoki sponsors gas, and the service key is therefore the on-chain owner of Namespace/Receipt objects (user wallet / zkLogin ownership deferred). Document this so the registry/receipt modules don't assume user-owned objects.

Sui Overflow angle

This is the foundation of the "real Sui-native contract" story — it turns ContextMEM from a consumer of Mysten packages into a publisher of its own on-chain logic, and gives judges a concrete packageId on a testnet explorer. Reproducible CI publish is what lets the team iterate the contract during the hackathon without manual key juggling.

Dependencies

None (this is the gating issue; registry, receipt, and the on-chain TS client all build on it).

Part of the ContextMEM roadmap (#4) • Sui Overflow build.

Activity

  1. added this to the Sui Overflow milestone on Jun 16, 2026
  2. added
    P0Demo-blocking: required for a working Sui Overflow demo
    moveSui Move smart-contract package (registry/receipt)
    suiSui chain: tx signing, objects, wallet, zkLogin, explorer
    platformBackend platform plumbing: Worker, D1, queues, secrets, metering
    on Jun 16, 2026
  3. harrymove-ctrl commented on Jun 19, 2026

    @harrymove-ctrl
    OwnerAuthor

    Implementation Plan

    Approach
    Stand up a single top-level move/contextmem/ package (sibling to apps//packages/) containing Move.toml (edition 2024.beta, contextmem = "0x0", explicit Sui framework dep pinned to a testnet tag), two empty-but-compiling module stubs (registry, receipt), and a trivial tests/ module so sui move test is green. Add a dedicated .github/workflows/move.yml that is path-scoped to move/** (never touching the JS-only bun-check.yml): a PR/push job that installs a pinned, cached prebuilt Sui CLI binary (no cargo install) and runs sui move build + sui move test, plus a separate workflow_dispatch publish job that imports SUI_TESTNET_PRIVATE_KEY, faucets gas, runs sui client publish --json, and emits published.testnet.json (packageId + UpgradeCap + tx digest) as an artifact. Key design decision: keep this purely a scaffold — empty modules, no business logic — so the registry/receipt/TS-client issues have a stable on-chain address and a reproducible publish path to build on, and record the signer/network DECISION (testnet + service-key-signed, Enoki-sponsored runtime) in the README so sibling modules don't assume user-owned objects.

    Prerequisites & dependencies

    • Blocking issues: none. This is the gating issue (roadmap §2; registry, receipt, on-chain TS client all depend on it).
    • Open roadmap decisions this issue locks/records (not re-opens): docs: add product roadmap (Harbor storage + Talus on-chain direction) #4 network → testnet (co-locate with WALRUS_NETWORKS.testnet in packages/walrus/src/constants.ts:13 and Harbor testnet alpha); Spike: run @mysten/seal encrypt+decrypt inside a Cloudflare Worker #5 signer/ownership → single backend service key signs, Enoki sponsors runtime gas, service key owns objects (documented in README, not implemented here); Build HarborClient: reserve→sign→finalize bucket, multipart upload, status poll, download #6 service-key custody → noted as shared-vs-per-owner deferred.
    • External creds/bindings needed:
      • Repo SECRET SUI_TESTNET_PRIVATE_KEY in bech32 suiprivkey1... form (consumed by sui keytool import).
      • A Sui testnet address derived from that key, fundable via the testnet faucet (sui client faucet / https://faucet.testnet.sui.io/v2/gas). Publish needs real testnet SUI — Enoki sponsorship covers runtime txs only, not the one-time publish.
      • Optional repo VARIABLE MOVE_PUBLISH_ENABLED to gate the publish job (mirrors deploy.yml's DEPLOY_ENABLED pattern so forks stay green).
      • No Cloudflare / Vectorize / Harbor / @mysten/seal involvement in this issue.
    • Toolchain version to pin: choose the current Sui testnet release tag at implementation time (e.g. testnet-v1.51.x) and use the same tag for both the CLI binary and the Move.toml framework rev to avoid framework/CLI mismatch warnings.

    Step-by-step

    1. Create move/contextmem/Move.toml (new). Contents:

      [package]
      name = "contextmem"
      edition = "2024.beta"
      # license / authors optional
      
      [dependencies]
      Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "testnet-v1.51.4" }
      
      [addresses]
      contextmem = "0x0"

      Pin rev to the chosen testnet tag (keep it equal to the CI CLI version). Note: recent CLIs treat Sui as an implicit system dep and may warn the explicit dep is unnecessary — the issue explicitly requires it pinned, so keep it; if the CLI errors on the duplicate-system-dep, fall back to rev = "framework/testnet" or drop the block and rely on the implicit dep (document whichever in the README).

    2. Create stub modules (new):

      • move/contextmem/sources/registry.move → module contextmem::registry { }
      • move/contextmem/sources/receipt.move → module contextmem::receipt { }
        An empty module compiles under 2024.beta. Add a one-line //!-style comment in each pointing to its dedicated issue so the next engineer knows where the real Namespace / AttributionReceipt structs land.
    3. Wire tests/ (new) — move/contextmem/tests/contextmem_tests.move:

      #[test_only]
      module contextmem::contextmem_tests {
          #[test]
          fun scaffold_builds() { assert!(true, 0); }
      }

      This makes sui move test exit 0 with a passing test (proving the test harness is wired, not just "0 tests found"). Also add move/contextmem/.gitignore with build/ so compiled artifacts aren't committed.

    4. Create .github/workflows/move.yml (new) — build/test job:

      • Triggers: pull_request and push (branches main, staging) filtered to paths: ['move/**', '.github/workflows/move.yml'], plus workflow_dispatch. This keeps it independent of bun-check.yml (.github/workflows/bun-check.yml stays JS-only) — a JS-only PR shows move.yml as skipped, not run.
      • Reusable "install Sui CLI" step (a composite step or inline): download the prebuilt release tarball https://github.com/MystenLabs/sui/releases/download/<tag>/sui-<tag>-ubuntu-x86_64.tgz, extract the sui binary to ~/.sui/bin, add to $GITHUB_PATH. Cache it with actions/cache keyed on the tag (key: sui-cli-<tag>). Do not cargo install (per issue note). Also actions/cache the Move dep cache (~/.move) keyed on hashFiles('move/contextmem/Move.toml') so the framework git-clone is reused.
      • Steps: actions/checkout@v4 → restore CLI cache / install → sui move build --path move/contextmem → sui move test --path move/contextmem.
    5. Add the publish job to move.yml — publish-testnet:

      • if: github.event_name == 'workflow_dispatch' (and optionally && vars.MOVE_PUBLISH_ENABLED == 'true'). Add a guard step that fails with a clear message if secrets.SUI_TESTNET_PRIVATE_KEY == ''.
      • Install the same pinned Sui CLI (reuse the cached step).
      • Bootstrap client config non-interactively: create ~/.sui/sui_config/client.yaml for the testnet env (rpc: https://fullnode.testnet.sui.io:443), then sui keytool import "$SUI_TESTNET_PRIVATE_KEY" ed25519, resolve the imported address via sui keytool list --json, sui client switch --address <addr> and --env testnet. (First-run sui client is interactive — pre-writing config or piping yes avoids the prompt; document the exact incantation.)
      • Faucet: sui client faucet (falls back to curl -X POST https://faucet.testnet.sui.io/v2/gas -d '{"FixedAmountRequest":{"recipient":"<addr>"}}'); poll sui client gas --json until a coin appears.
      • Publish: sui client publish --path move/contextmem --json --gas-budget 200000000 --skip-dependency-verification > publish.json.
      • Extract & write move/contextmem/published.testnet.json with jq:
        • packageId = .objectChanges[] | select(.type=="published") | .packageId
        • upgradeCap = .objectChanges[] | select(.objectType? and (.objectType|test("::package::UpgradeCap$"))) | .objectId
        • txDigest = .digest; also record network: "testnet", sender, publishedAt.
      • actions/upload-artifact@v4 for published.testnet.json. (Recommend committing it back to the repo via a follow-up PR — avoid CI contents: write for alpha — so downstream issues read a stable address from the repo.)
    6. Create move/contextmem/README.md (new) documenting: local build (sui move build --path move/contextmem, sui move test, bun run move:build); the named-address convention (contextmem = "0x0" placeholder → publish assigns the real id; downstream builds can override with --named-addresses contextmem=<packageId>); the UpgradeCap convention (future changes use sui client upgrade with the captured cap, never republish to a new address); and the DECISION (per issue notes + roadmap docs: add product roadmap (Harbor storage + Talus on-chain direction) #4/Spike: run @mysten/seal encrypt+decrypt inside a Cloudflare Worker #5): testnet launch surface; runtime mints Enoki-sponsored; the suiprivkey1... service key (decoded via Ed25519Keypair/decodeSuiPrivateKey) is the sender/signer and on-chain owner of Namespace/Receipt objects; user-wallet/zkLogin ownership deferred — so registry/receipt must not assume user-owned objects.

    7. Edit root package.json (/Users/harryphan/Documents/contextMeM/package.json, scripts block ~line 16-27): add "move:build": "sui move build --path move/contextmem" (optionally "move:test": "sui move test --path move/contextmem"). Keep it out of the check/build aggregates so the JS CI/dev flow doesn't require the Sui CLI.

    New / changed files

    • move/contextmem/Move.toml (new)
    • move/contextmem/sources/registry.move (new)
    • move/contextmem/sources/receipt.move (new)
    • move/contextmem/tests/contextmem_tests.move (new)
    • move/contextmem/.gitignore (new — build/)
    • move/contextmem/README.md (new)
    • move/contextmem/published.testnet.json (produced by the publish job as an artifact; committed back via follow-up PR after first successful publish)
    • .github/workflows/move.yml (new)
    • package.json (edit — add move:build script)

    Test plan

    Risks & gotchas

    • Sui CLI install cost: cargo install is too slow — must use the prebuilt release tarball + actions/cache. Asset naming has shifted across releases (e.g. sui-<tag>-ubuntu-x86_64.tgz); confirm the exact asset name for the chosen tag, or use suiup as an alternative installer.
    • Framework/CLI version mismatch: if Move.toml rev and the CI CLI tag diverge, builds emit framework-version warnings or fail. Keep them equal; pin a concrete testnet-vX.Y.Z tag rather than the moving framework/testnet branch for reproducibility.
    • First-run sui client is interactive (prompts to create config/key). Pre-write ~/.sui/sui_config/client.yaml or pipe answers; otherwise the publish job hangs.
    • Faucet flakiness / rate limits: testnet faucet throttles per IP/address and is occasionally down → publish job fails. Mitigate by pre-funding the service address once and treating the faucet step as best-effort (proceed if gas already present); add a short retry.
    • Enoki ≠ publish gas: sponsorship covers runtime txs only; the one-time publish needs real SUI (per issue + roadmap note). Set --gas-budget explicitly (~0.2 SUI) so a dry-run estimate failure doesn't block.
    • Network split: must publish to testnet to co-locate with Walrus/Harbor testnet (roadmap decision docs: add product roadmap (Harbor storage + Talus on-chain direction) #4); a stray mainnet publish breaks cross-referencing receipts↔blobs.
    • published.testnet.json write-back: committing from CI needs contents: write + a bot commit; default to artifact-only + manual follow-up PR to avoid granting CI write perms.
    • Empty-module / edition support: 2024.beta is required for the empty-module + label syntax; verify the pinned CLI supports it (recent testnet releases do).

    Acceptance-criteria mapping

    • AC1 (move/contextmem/ + Move.toml edition/named-address/framework rev + sources/) → Step 1 (+ dir from Steps 2).
    • AC2 (compiling registry.move/receipt.move stubs + tests/ so sui move test green) → Steps 2, 3; verified by local test plan.
    • AC3 (new move.yml installs Sui CLI, runs build+test on PRs touching move/**, not overloading bun-check.yml) → Step 4.
    • AC4 (workflow_dispatch publish job using SUI_TESTNET_PRIVATE_KEY + faucet, writes published.testnet.json as artifact) → Step 5.
    • AC5 (README.md documents local build + named-address/upgrade-cap conventions + signer/network decision) → Step 6.
    • AC6 (root package.json move:build script) → Step 7.

    Effort: S–M, ~1–1.5 person-days. The Move scaffold + README + package.json edit is ~2 hours; the bulk is the move.yml publish job (cached pinned CLI install, non-interactive client config, faucet, JSON parsing) and one real end-to-end testnet publish to validate the digest.


    Implementation plan generated for execution (planning phase). Part of the roadmap (#4).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Demo-blocking: required for a working Sui Overflow demomoveSui Move smart-contract package (registry/receipt)platformBackend platform plumbing: Worker, D1, queues, secrets, meteringsuiSui chain: tx signing, objects, wallet, zkLogin, explorer

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions