feat(dashboard): four-tab detail UI with routing + sandbox config

Restructures the script detail page from one wall of cards into a
focused four-tab layout. Each tab does one thing well:

  * Edit       source editor + Test invoke panel (the existing
               quick-iteration loop, unchanged in shape)
  * Routing    routes table + add-route form with live kind
               auto-detection + match-preview tool
  * Settings   name / description / timeout, plus a collapsible
               "Advanced sandbox" disclosure with the six Rhai
               limits (admin-ceiling-validated server-side)
  * Executions the existing log viewer, gets the room it deserves

Why four tabs (not two columns, not one tab per surface, not URL
sub-routes):
  * Two columns crowded out the routing UX, which is genuinely
    list+form-shaped and wants vertical space.
  * URL sub-routes (/scripts/{id}/routing) would let users
    bookmark a tab but cost a bunch of router files for a
    feature nobody asked for; tab state in $state is one line
    and gets us 95% of the UX.
  * Sandbox config tucked inside Settings' "Advanced" disclosure
    matches the 95%-never-touch reality without hiding it.

Routing tab highlights:
  * Path input + path-kind selector with live auto-detect: type
    /greet/:name and the kind selector flips to "param"; the
    user can override and the backend trusts the override (lets
    /greet/:name be matched literally if exact is selected).
  * Soft warning when selection mismatches the input shape — not
    blocking, with the rationale in the message.
  * Host kind auto-detect mirrors the path side (*.example.com →
    wildcard; non-empty literal → strict; empty → any).
  * Method dropdown defaults to ANY.
  * 409 conflicts render inline with the conflicting route's
    method/host/path so the user can read both at a glance.
  * Match-preview panel: synthetic URL + method → "matches THIS
    script" or "matches a DIFFERENT script" or "no match", with
    extracted params shown. Powered by /api/v1/admin/routes:match.
  * Full URLs in the routes list use the operator's
    PICLOUD_PUBLIC_BASE_URL from /version.

Settings tab:
  * Name / description / timeout editable from the UI for the
    first time (previously only source was).
  * "Advanced sandbox" details element collapsed by default;
    six number inputs with placeholder "(default)" meaning
    "use platform default for this knob". Save sends a fresh
    sandbox object; ceiling errors surface as the manager's 422
    message inline.

API client (dashboard/src/lib/api.ts):
  * Adds `Route`, `RouteInput`, `CheckRouteResponse`,
    `MatchRouteResponse`, `ScriptSandbox`, `VersionInfo` types.
  * Adds `api.routes.{listForScript,create,remove,check,match}`.
  * Adds `api.version()`.
  * `UpdateScriptInput` gains `sandbox`.

route-utils.ts:
  * `guessPathKind`, `guessHostKind` heuristics.
  * `pathKindMismatchWarning` for the soft-warning UX.

Verified live:
  /admin/                       → 200, dashboard HTML
  /admin/scripts/<id>           → SPA detail with all four tabs
  POST /api/v1/admin/scripts/<id>/routes → 201, route persists
  GET /demo/widget              → 200 (script answers via routing
                                    table after the dashboard's
                                    POST refreshes it)
  /version                      → public_base_url, schema 3, sdk 1.1

No backend changes — Commit 3 is purely additive UI on top of the
infrastructure Commits 1 and 2 already shipped.

Bumps: product 0.4.0 → 0.5.0 (user-visible UX change). Schema, SDK,
API, wire unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-05-23 22:07:36 +02:00
parent 07e2a62d98
commit ed462726de
7 changed files with 892 additions and 189 deletions

View File

@@ -124,7 +124,7 @@ A surface can hit its own `1.0` independently of the product. The SDK in particu
| | Version |
|---|---|
| Product | `0.4.0` |
| Product | `0.5.0` |
| SDK | `1.1` (adds `ctx.request.params`, `ctx.request.query`, `ctx.request.rest`) |
| API | `1` |
| Schema | `3` (matches `migrations/0003_routes.sql`) |