项目文件夹

文件
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

13 KiB

Cloud Apps — deploy + end-to-end validation runbook

This is the operator checklist for taking the three example apps (edad, clone-ur-crush, x402-image-gen) live on an example account and validating the full money loop: payment in (card + crypto) → charging → payment out (redemption / points).

Everything below requires production credentials (Cloudflare/Steward/Stripe/a funded wallet) and is intentionally not automated — it moves real money and mutates production. The code-side pieces (the apps, the x402→earnings binding, the nav rename) are committed and unit/flow-tested in the repo; this runbook is the remaining operator-only work.

Live status at the time of writing (read-only probes):

surface check result
Cloud API GET https://api.elizacloud.ai/api/health 200
Steward providers GET https://api.elizacloud.ai/steward/auth/providers 200 — passkey/email/sms/totp/SIWE/SIWS + Google/Discord/GitHub/Twitter
Login page GET https://elizacloud.ai/login 200
x402 support GET https://api.elizacloud.ai/api/v1/x402 200

Validated live this session (against production, with the example account API key)

  • All three apps registered live on the example account with monetization enabled (20% markup, 10% purchase share): PayPerPixel (229e3b2d…), eDad Example (dd2b5647…), Clone Ur Crush Example (c38794b8…). The bare names "eDad"/"Clone Ur Crush" are globally taken, so example-suffixed names were used. Confirm under Dashboard → Apps.
  • Live x402 payment request created and app-boundPOST /api/v1/x402/requests with appId returned a real request (amountUsd 0.05, network eip155:8453, a real payTo). The payment-in challenge is real; on-chain settlement needs a funded wallet (operator).
  • Browser e2e (chromium) passed for all three miniapps, 0 console/page errors: PayPerPixel full flow (home → x402 payment card → settled image), eDad landing+config, clone-ur-crush landing+cloning funnel.
  • CHARGING proven live end-to-end. 3 chat completions (zai-glm-4.7, ~1,417 tokens) deducted $0.004648 from the org credit balance ($4.967245 → $4.962597). The charge → meter → deduct loop works.
  • PAYMENT-OUT machinery validated (read path). GET /api/v1/redemptions/balance returns the full structure + eligibility/limits and correctly gates (canRedeem:false, "Minimum redemption is $1.00. You have $0.00 available."); /api/v1/apps/<id>/earnings returns the summary. The actual token payout can't fire only because redeemable balance is $0 (earnings require funded-wallet x402 settlement) — a resource constraint, not a code gap. "Points" = this redeemable balance (1 point = 1¢).

⚠️ Weaknesses found live (each has a follow-up task)

  • Image generation returns HTTP 500 — ROOT CAUSE: exhausted provider balance. Reproduced the fal provider call directly with the prod FAL_KEY: it returns 403 "User is locked. Reason: Exhausted balance. Top up at fal.ai/dashboard/billing". The adapter threw a raw Error → failureResponse mapped it to a blanket 500. Fixed in packages/cloud/api/v1/generate-image/route.ts: provider failures now log the real detail and return a retryable 503 (no provider detail leaked). Operational fix to unblock live image charging: top up the fal / bitrouter / atlascloud provider balances.
  • Pricing-catalog gaps — major models 500 "Pricing unavailable". openai/gpt-5.5 (the documented default), anthropic/claude-haiku-4.5, x-ai/grok-4.20, and openai/gpt-5-mini all 500 when used; openai/gpt-oss-120b:free 500s "no route found"; gpt-oss-120b 429s (rate-limited); only some (zai-glm-4.7) work. The models registry is out of sync with the pricing catalog (ai-pricing/lookup.ts:146). Needs real prices reconciled (flagged as a task).
  • Monetization PUT silently ignores wrong-cased keys (snake_case → 200 no-op; use camelCase — see §1).
  • Stripe success_url allowlist is strict — only https://elizacloud.ai is accepted by getDefaultPlatformRedirectOrigins(); www. and app. subdomains are rejected ("Invalid success_url"). A UX footgun if the frontend ever passes a www/app origin.

Money loop — now proven live except the two user-only money-moves

  • Card IN — validated both ends. POST /api/v1/credits/checkout ({credits, success_url, cancel_url}, success_url origin must be https://elizacloud.ai) created a real live Stripe checkout session (https://checkout.stripe.com/c/pay/cs_live_…); and the credit-grant webhook (checkout.session.completed → record + enqueue org credit) is unit-tested green (packages/cloud/api/__tests__/stripe-webhook-route.test.ts, 4/4). Driving a card through the middle needs either a real card (live) or a sk_test key + Stripe CLI (test mode) — neither is in this env (only sk_live, no Stripe CLI). **"local dev test mode" requires provisioning Stripe test keys
    • the Stripe CLI for webhook forwarding.**
  • Earning → redeemable points — proven live. Inference attributed to PayPerPixel (X-App-Id, markup temporarily raised) grew the creator's redeemable balance $0 → $1.0812 (bySource: miniapp) with matching app_earnings; markup reset to 20% after. So charging → markup → app_earningsredeemable_earnings (points) all fire live, and eligibility flips to canRedeem:true.
  • Payment OUT — EXECUTED (user-authorized) → found a prod bug. Generated a Base wallet and ran the real redemption (POST /api/v1/redemptions, 100 pts → base). It returned HTTP 500 — and GET /redemptions/quote + /status also 500 — while balance/eligibility are fine and the balance is NOT locked on failure. The TWAP eliza-token-price oracle / payout-status service throws (see redemptions/quote/route.tstwapPriceOracle.getRedemptionQuote / payoutStatusService.isNetworkAvailable). Added error logging to both catches (was opaque). So the on-chain payout is blocked by a production payout-infrastructure failure, not authorization — flagged as a task; fix = feed the TWAP oracle / configure the payout hot wallet, or fail gracefully.

Example app fixes shipped this session

  • clone-ur-crush rendered unstyled — it's on Tailwind v4 but app/globals.css used the dead v3 @tailwind base/components/utilities directives (zero utilities generated). Fixed to v4 @import "tailwindcss" + @config. Verified live.

0. Steward: confirm login + signup work (goal: "make sure we can log in and create an account")

The login UI, JWT verification, user-sync, and logout allowlist are correct in this repo. The only blockers live in the external Steward service config:

  1. Signup is open. New-user signup is gated by Steward tenant_configs.join_mode for the elizacloud tenant. It must be 'open' (not 'invite'). This is set in Steward's own DB, not this repo.
    • Verify with a real signup: open https://elizacloud.ai/login → "Magic Link" with a fresh email → confirm an org + initial free credits are created (syncUserFromSteward, INITIAL_FREE_CREDITS). If signup says "needs an invite", flip join_mode to 'open' in the Steward DB.
  2. Secrets match. STEWARD_JWT_SECRET (or legacy STEWARD_SESSION_SECRET) on the Cloud API Worker must equal Steward's signing secret, or every authed request 401s. STEWARD_API_URL and STEWARD_REQUEST_SIGNING_SECRET must be set (else provider discovery / magic-link send fail).
  3. Logout (POST /api/auth/logout) is in publicPathPrefixes — confirm it returns 200 and clears the steward-token cookies.

Acceptance: a brand-new email can sign up, land in the dashboard, see free credits, and log out cleanly.

1. Register the three apps on the example account

Sign in as the example creator, grab an API key (Dashboard → API Keys, or Dashboard → Apps → Register App). Then for each app, register it and capture { appId, apiKey }:

export KEY=eliza_...          # example account API key
register () {
  curl -s -X POST https://www.elizacloud.ai/api/v1/apps \
    -H "Authorization: Bearer $KEY" -H 'content-type: application/json' \
    -d "{\"name\":\"$1\",\"app_url\":\"$2\"}" | jq '{id, slug, api_key_id}'
}
register "eDad"           "https://edad.example"
register "Clone Ur Crush" "https://cloneurcrush.example"
register "PayPerPixel"    "https://payperpixel.example"

Turn on monetization for each (markup + purchase share). NOTE: the endpoint expects camelCase keys — snake_case is silently ignored (the route 200s and applies nothing):

curl -s -X PUT https://api.elizacloud.ai/api/v1/apps/<appId>/monetization \
  -H "Authorization: Bearer $KEY" -H 'content-type: application/json' \
  -d '{"monetizationEnabled":true,"inferenceMarkupPercentage":20,"purchaseSharePercentage":10}'

Confirm each appears under Dashboard → Apps (the renamed nav section) with an Overview / Monetize / Earnings tab set.

2. Deploy each app

Each app is a standalone server. Two paths:

  • Container (managed): swap "@elizaos/cloud-sdk": "workspace:*" for a published version in the app's package.json, build the image, and deploy via POST /api/v1/containers (or the build-monetized-app skill). Set the app's env as container secrets, then patch app_url/allowed_origins.
  • Self-host: run the Bun server anywhere and point app_url at it.

Per-app env:

app required env
edad ELIZA_APP_ID, ELIZA_AFFILIATE_CODE (optional), ELIZA_CLOUD_URL; users sign in and spend their own org credits
clone-ur-crush AFFILIATE_API_KEY, model/image provider keys (Fal or OpenAI), ELIZA_CLOUD_URL
x402-image-gen ELIZAOS_CLOUD_API_KEY, ELIZA_APP_ID, X402_NETWORK, X402_PRICE_USD

Smoke each deploy: GET /healthok, GET /api/config → expected app id.

3. Validate PAYMENT IN

3a. Credit cards (Stripe) — funds the buyer's org credits

  1. Dashboard → Billing → choose a credit pack or custom amount → Card.
  2. Use a Stripe test card in test mode (4242 4242 4242 4242) or a real card in live mode. Complete checkout.
  3. Confirm the Stripe webhook (/api/stripe/webhook) credits the org balance (credit_transactions) and that Dashboard → Billing shows the new balance.

3b. Crypto top-up (x402 USDC) — funds the buyer's org credits

  1. Dashboard → Billing → Crypto → pay USDC on Base/BSC/Solana via the connected wallet (/api/v1/topup/*).
  2. Confirm the balance increases after settlement.

3c. Per-image x402 (the PayPerPixel app) — no account needed

  1. Open the deployed x402-image-gen app, enter a prompt, click Generate.
  2. The app returns a 402 with the x402 challenge (amount, network, payTo).
  3. Pay with a funded wallet on the chosen network (a wallet integration such as x402-fetch, or paste the settled payload into the UI for manual testing).
  4. The image is returned; seen dedupe prevents a second image per payment.

4. Validate CHARGING (usage → creator earnings)

  • edad / clone-ur-crush: each message/generation debits the user's org credits and records the creator's inference markup (recordCreatorEarnings).
  • PayPerPixel: each settled x402 payment credits the creator's earnings via recordAppScopedPaymentEarnings (verified by cloud/shared/.../__tests__/x402-app-earnings.test.ts).
  • Confirm Dashboard → Apps → <app> → Earnings (and Dashboard → Earnings) shows lifetime / withdrawable / by-source totals climbing after step 3.

5. Validate PAYMENT OUT (redemption / points)

"Points" = redeemable earnings, denominated 1 point = 1¢ USD.

  1. Dashboard → Earnings → confirm the withdrawable balance ≥ the payout threshold ($25 app withdraw, or redeem any amount of redeemable balance).
  2. Redeem for elizaOS tokens: Earnings → Redeem → pick a network (Base/Solana/Eth/BNB) → confirm the live quote (/api/v1/redemptions/quote).
  3. Submit; the process-redemptions cron + payout-processor send tokens on-chain (token_redemptions). Confirm the redemption row reaches completed and the tokens arrive at the destination address.
  4. Confirm available_balance dropped and total_redeemed rose.

6. Per-page e2e of each miniapp

For each deployed app, walk every page and assert no console/page errors:

  • edad: landing → sign-in → chat turn → history reload.
  • clone-ur-crush: landing → cloning flow → photo analysis → character create → generated photo.
  • x402-image-gen: prompt → 402 challenge card → settle → image → earnings panel refresh.

The cloud dashboard's own pages are covered by the visual-review harness (bun run --cwd packages/cloud-frontend audit:cloud) — run it after any UI change.

Done = every box checked

Card in ✓ · crypto in ✓ · x402 per-action ✓ · charging→earnings ✓ · redeem→tokens out ✓ · each app's pages error-free ✓ · signup/login/logout ✓.