Files
agentic-mobile-control/cloud-console
q792602257andClaude Opus 4.6 2169bb03d9 feat(cloud-console): task listing, attempt history, CORS, and console SPA
Implements the cloud-console OpenSpec change: adds GET /v1/tasks (filterable,
bounded pagination, tasks:read) and GET /v1/tasks/{id}/attempts (404 on unknown
task) to the platform SDK, with matching CloudClient methods and a closed-by-
default CLOUD_CONSOLE_CORS_ORIGINS allow-list wired through CloudControlConfig.
Ships an independent Vue 3 + Vite SPA at cloud-console/ that authenticates with
an operator-supplied bearer token held in sessionStorage, renders tasks with
attempt history, device pool, host registry, and the plugin registry with a
registration form.

Backend test suite: 438 passed (-m "not integration"); cloud-console typecheck
and production build both succeed. PostgreSQL-backed repository tests and
manual end-to-end verification remain pending external infrastructure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-13 14:00:23 +08:00
..

Cloud Console

Independent Vue 3 + Vite single-page app for the Cloud Control Plane (apps/cloud-api). Operators authenticate by pasting a pre-issued scoped bearer token; the console stores it in sessionStorage, attaches Authorization: Bearer <token> to every request, and clears it whenever the Cloud API responds 401 or 403.

The app talks only to the platform SDK surface (/v1/...) and consumes the two listing endpoints added by the cloud-console change (GET /v1/tasks, GET /v1/tasks/{task_id}/attempts) alongside the existing /v1/devices, /v1/hosts, /v1/plugins, and POST /v1/plugins routes.

Prerequisites

  • Node.js 20+ (matching the existing console/ SPA project)
  • A running Cloud API (apps/cloud-api) reachable from your browser
  • A bearer token issued via CLOUD_PUBLIC_CREDENTIALS_JSON whose scopes cover what you intend to do from the console. Recommended least-privilege set:
    • tasks:read — task list and attempt history views
    • pool:read — device and host views
    • plugins:read — plugin list
    • Add tasks:submit/plugins:admin only if you need the write actions from the same tab.

Configure the backend CORS allow-list

The Cloud API has no CORS middleware by default. Before a browser can call it cross-origin, set CLOUD_CONSOLE_CORS_ORIGINS to a comma-separated allow-list that includes the exact origin your dev server prints (scheme + host + port — no trailing slash):

# Example: allow the default Vite dev origin
export CLOUD_CONSOLE_CORS_ORIGINS="http://127.0.0.1:5173"

Restart apps/cloud-api after changing this env. Tokens are still required — the allow-list only says which browser origins may send them.

Run the dev server

cd cloud-console
cp .env.example .env.local
# Edit .env.local if your Cloud API is not at http://127.0.0.1:8001
npm install
npm run dev

Vite prints a local URL (default http://127.0.0.1:5173). Open it, paste a bearer token, and the task/device/host/plugin dashboards become available.

.env.local overrides the default base URL via VITE_CLOUD_API_BASE_URL (defaults to http://127.0.0.1:8001).

Build for production

npm run build      # type-checks with vue-tsc, then emits dist/
npm run preview    # serves the built bundle locally

dist/ is a static bundle — host it behind any static file server or CDN and point it at a deployed Cloud API via VITE_CLOUD_API_BASE_URL set at build time.

Token handling

  • The token is held in sessionStorage only. Closing the tab discards it.
  • Every API request attaches Authorization: Bearer <token> and targets only the configured VITE_CLOUD_API_BASE_URL.
  • A 401/403 response clears the stored token and returns the operator to the token-entry screen with the API's error detail.

Project layout

cloud-console/
├── src/
│   ├── api.ts               # API client wrapper (token storage, fetch, errors)
│   ├── types.ts             # TS interfaces mirroring the REST models
│   ├── App.vue              # Shell: token gate, nav, view router
│   ├── main.ts              # Vue bootstrap
│   ├── style.css            # Dark theme styles
│   └── views/
│       ├── TokenScreen.vue
│       ├── TasksView.vue        # list + detail with attempt history
│       ├── DevicesView.vue      # device pool + host registry
│       └── PluginsView.vue      # registry list + registration form
├── index.html
├── package.json
├── tsconfig.json / tsconfig.node.json
└── vite.config.ts