Files
q792602257andClaude Opus 4.6 e00c50e703 feat(api): server-rendered Jinja2 Runtime console at /ui/
Replaces the separate Vue/Vite `console/` SPA with a same-origin,
server-rendered console built on a module-level Jinja2 Environment
with select_autoescape(["html","xml"]).

- Add api/console_web.py with /ui/ routes (dashboard, tasks, task
  detail/timeline, config) and a _status_fragment polled every 10s.
- Refactor api/console.py into a typed ConsoleService shared by the
  JSON and HTML routers so validation/persistence cannot drift.
- Remove RUNTIME_CONSOLE_STATIC_DIR, SpaStaticFiles, and the wildcard
  CORS middleware from api/rest.py; GET / now redirects to /ui/.
- Delete the top-level console/ project; add jinja2 and python-multipart
  as direct dependencies and ship templates/CSS/JS via package-data.
- Add 31 tests (XSS probes, PRG flows, fragment refresh, no-static-dir
  and no-CORS regressions, wheel-packaging smoke test).

/console/* JSON endpoints remain unchanged. The console keeps the
trusted-network-only boundary; auth/CSRF is intentionally deferred.

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

61 lines
2.9 KiB
Markdown

## Why
The local Runtime console is currently a separately built Vue/Vite SPA. It
requires a Node toolchain for development and an optional static-directory
configuration for same-process serving, even though its data and mutations
already live in the Runtime FastAPI process. Rendering the console with Jinja2
will make the operator surface deploy with the Runtime itself while preserving
the existing REST contract for programmatic clients.
## What Changes
- Add a same-origin, server-rendered Runtime console under `/ui/`, with Jinja2
pages for device status, task browsing/detail/timeline replay, device
registration/removal, and runtime configuration.
- Keep the existing `/console/*` JSON endpoints and make page handlers and
JSON handlers share API-layer console operations so their observable
registration, deletion, filtering, and configuration semantics cannot
drift.
- Package console templates and static assets with `device-agent-runtime`, add
direct Jinja2 and HTML form-parsing dependencies, and render every HTML page
through one autoescaping template environment.
- Replace the Vue/Vite `console/` project, `RUNTIME_CONSOLE_STATIC_DIR`, and
SPA fallback static mount with Runtime-owned templates and normal static
assets. Remove the permissive CORS configuration that existed only for
cross-origin Vite development.
- **BREAKING**: the independent `console/` npm workflow and
`RUNTIME_CONSOLE_STATIC_DIR` deployment mode are removed. Operators will
start the Runtime API normally and open `/ui/`; JSON API paths remain
unchanged.
## Capabilities
### New Capabilities
- `runtime-console-template-rendering`: Same-origin Jinja2-rendered Runtime
console pages, automatic HTML escaping, form-based mutations, and packaged
Runtime-owned web assets.
### Modified Capabilities
- None. The existing canonical specs do not define the pending `web-console`
SPA, and the `/console/*` JSON API contract remains unchanged.
## Impact
- Affected code: `api/rest.py`, `api/console.py`, a new API-layer page router,
Runtime template/static asset directories, root `pyproject.toml`, and
console-focused tests.
- Removed code/assets: top-level `console/` Vue/Vite sources, Node lockfile,
Vite environment configuration, and SPA deployment wiring.
- Documentation: Runtime startup and console guidance in `README.md`,
`docs/CONSTITUTION.md`, and `docs/MACOS_IPHONE_SETUP.md` change to describe
the built-in `/ui/` console.
- Security boundary: this change preserves the existing trusted-network,
unauthenticated Runtime console assumption. It does not add authentication,
authorization, or session/CSRF protection; non-trusted exposure needs a
separate security change.
- Architecture: all new HTTP, HTML, and template concerns remain in the outer
`api` layer. No `core`, `driver`, `device`, `tools`, `perception`, or
`runtime` package gains web-framework dependencies.