Skip to content

Commit e82281f

Browse files
committed
chore: prepare 0.6.0 release
1 parent e40a36f commit e82281f

10 files changed

Lines changed: 810 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Changelog
22

3-
## 0.6.0 - Unreleased
3+
## 0.6.0 - 2026-05-07
44

55
### Added
66

docs/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ Run history and inspection are intentionally handled by the Crabbox CLI and repo
7777
Pick whichever matches your intent:
7878

7979
- **Get the mental model:** [How Crabbox Works](how-it-works.md), [Architecture](architecture.md), [Orchestrator](orchestrator.md).
80-
- **Use the CLI:** [CLI](cli.md), [Commands](commands/README.md), [Features](features/README.md), [Actions hydration](features/actions-hydration.md).
81-
- **Pick or add a target:** [Provider reference](providers/README.md), [Providers feature overview](features/providers.md), [Provider backends](provider-backends.md), [AWS](providers/aws.md), [Hetzner](providers/hetzner.md), [Static SSH](providers/ssh.md), [Blacksmith Testbox](providers/blacksmith-testbox.md), [Daytona](providers/daytona.md), [Islo](providers/islo.md), [Interactive desktop and VNC](features/interactive-desktop-vnc.md).
80+
- **Use the CLI:** [CLI](cli.md), [Commands](commands/README.md), [Features](features/README.md), [Actions hydration](features/actions-hydration.md), [Browser portal](features/portal.md), [Telemetry](features/telemetry.md).
81+
- **Pick or add a target:** [Provider reference](providers/README.md), [Providers feature overview](features/providers.md), [Provider authoring](features/provider-authoring.md), [Provider backends](provider-backends.md), [AWS](providers/aws.md), [Hetzner](providers/hetzner.md), [Static SSH](providers/ssh.md), [Blacksmith Testbox](providers/blacksmith-testbox.md), [Daytona](providers/daytona.md), [Islo](providers/islo.md), [Interactive desktop and VNC](features/interactive-desktop-vnc.md).
8282
- **Operate it:** [Operations](operations.md), [Observability](observability.md), [Troubleshooting](troubleshooting.md), [Performance](performance.md).
8383
- **Set it up or audit it:** [Infrastructure](infrastructure.md), [Security](security.md), [Source Map](source-map.md), [MVP Plan](mvp-plan.md).
8484

docs/features/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ Core features:
1212

1313
- [Coordinator](coordinator.md): brokered leases through Cloudflare Workers and Durable Objects.
1414
- [Broker auth and routing](broker-auth-routing.md): GitHub login, shared bearer tokens, optional Cloudflare Access, and Worker routes.
15+
- [Browser portal](portal.md): authenticated lease/run UI, detail pages, bridge routes, and runner visibility.
1516
- [Providers](providers.md): provider overview, target matrix, classes, and fallback.
1617
- [Provider backends](../provider-backends.md): implementation guide for adding a new provider/backend/plugin.
18+
- [Provider authoring](provider-authoring.md): step-by-step guide for adding a provider package.
1719
- [AWS](aws.md): EC2 Linux, Windows, WSL2, EC2 Mac, capacity, AMIs, and security groups.
1820
- [Hetzner](hetzner.md): Linux-only managed Hetzner behavior, classes, and cleanup.
1921
- [Blacksmith Testbox](blacksmith-testbox.md): delegated Testbox backend behavior.
@@ -30,6 +32,7 @@ Core features:
3032
- [SSH keys](ssh-keys.md): per-lease keys, provider key cleanup, and local storage.
3133
- [Cost and usage](cost-usage.md): guardrails, provider-backed pricing, and reporting.
3234
- [History and logs](history-logs.md): coordinator run records, events, and retained remote output.
35+
- [Telemetry](telemetry.md): lightweight Linux load, memory, disk, uptime, and run resource samples.
3336
- [Test results](test-results.md): JUnit summaries attached to recorded runs.
3437
- [Cache controls](cache.md): inspect, purge, and warm remote package/build caches.
3538
- [Auth and admin](auth-admin.md): login/logout/whoami and trusted operator controls.

docs/features/portal.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# Browser Portal
2+
3+
Read when:
4+
5+
- using the web UI to inspect leases or runs;
6+
- changing portal pages or page-level routes;
7+
- deciding whether a feature should land in the CLI, the API, or the portal.
8+
9+
The browser portal is a small server-rendered web UI hosted by the same
10+
Cloudflare Worker that backs the Crabbox API. It is not a separate frontend
11+
or single-page app: every page is HTML rendered by the Worker, with light
12+
client-side JavaScript only for filtering, sorting, and clipboard copy.
13+
14+
## URL Map
15+
16+
```text
17+
GET /portal
18+
GET /portal/leases/{id-or-slug}
19+
POST /portal/leases/{id-or-slug}/release
20+
GET /portal/leases/{id-or-slug}/vnc
21+
GET /portal/leases/{id-or-slug}/code/
22+
GET /portal/runs/{run-id}
23+
GET /portal/runs/{run-id}/logs
24+
GET /portal/runs/{run-id}/events
25+
GET /portal/runners/{provider}/{runner-id}
26+
```
27+
28+
Portal authentication uses a browser session cookie minted after a successful
29+
GitHub login through the same OAuth flow as `crabbox login`. The cookie
30+
carries owner/org claims; the Worker scopes every page to that identity. Raw
31+
Cloudflare Access headers are not trusted - only a verified Access JWT email
32+
can become the portal owner.
33+
34+
## Lease Index `/portal`
35+
36+
The index renders a searchable, paginated, sortable lease grid. Columns
37+
include compact provider/target badges, icon-only access capabilities (SSH,
38+
VNC, code, browser), relative time cells, dense rows, and sticky column
39+
headers. Filters at the top of the page select active, ended, provider,
40+
target, or all.
41+
42+
Default view rules:
43+
44+
- Defaults to active leases when any are active.
45+
- Falls back to all visible leases when the active list is empty.
46+
- Normal browser sessions see only their own owner/org leases.
47+
- Admin sessions also see non-owned runner leases. `mine` and `system`
48+
filters distinguish personal leases from external runners (Blacksmith
49+
Testboxes synced from CLI list output) so external rows do not leak to
50+
normal users.
51+
52+
External runner rows render in the same grid as muted, disabled rows. They
53+
include status/provider filters, inferred GitHub Actions run/workflow links,
54+
status badges, `stuck` markers for long-queued or long-running Actions
55+
owners, a copyable local stop command, and stale markers when the next
56+
runner sync no longer sees a previously visible runner. Clicking an
57+
external runner opens `/portal/runners/{provider}/{runner-id}`, a
58+
visibility-only detail page.
59+
60+
## Lease Detail `/portal/leases/{id-or-slug}`
61+
62+
The lease detail page shows:
63+
64+
- compact provider/target badges and the lease state pill;
65+
- bridge status (whether the WebVNC and code-server bridges are up);
66+
- the latest Linux telemetry sample as gauges, with sparklines when multiple
67+
samples are present;
68+
- stale-telemetry, high-load, high-memory, and high-disk status pills when
69+
thresholds are exceeded;
70+
- an access panel with copy-to-clipboard commands for `crabbox ssh`,
71+
`crabbox run`, `crabbox webvnc`, and `crabbox code`;
72+
- a viewport-fitted "recent runs" grid with state filters;
73+
- a stop action when the lease is releasable.
74+
75+
`/portal/leases/{id-or-slug}/vnc` and `/portal/leases/{id-or-slug}/code/`
76+
are bridges, not portal pages. They proxy WebSocket and HTTP traffic to the
77+
matching capability on the lease so a user does not need an SSH tunnel to
78+
open the desktop or editor. See
79+
[Interactive desktop and VNC](interactive-desktop-vnc.md) and
80+
[code command](../commands/code.md).
81+
82+
## Run Detail `/portal/runs/{run-id}`
83+
84+
Run detail mirrors the `/v1/runs/...` resources but uses the browser session
85+
cookie, so users can inspect logs and events without copying a bearer token
86+
into the browser. The page renders:
87+
88+
- the command, owner, lease, provider metadata, and exit status;
89+
- a JUnit summary when the run attached results;
90+
- a searchable, paginated event table with event-type filters;
91+
- a copyable retained log tail;
92+
- bounded load, memory, and disk trend lines for longer Linux runs that
93+
attached mid-run telemetry samples.
94+
95+
`/portal/runs/{run-id}/logs` returns the retained log as plain text.
96+
`/portal/runs/{run-id}/events` returns the events as JSON. Both stay raw on
97+
purpose so they are easy to copy or pipe.
98+
99+
## Runner Detail `/portal/runners/{provider}/{runner-id}`
100+
101+
External runner detail is visibility-only. It shows:
102+
103+
- owner/org;
104+
- inferred GitHub Actions ownership (workflow, run id, status);
105+
- lifecycle timestamps;
106+
- boundary notes that explain Crabbox cannot stop or release the runner;
107+
- a copyable local stop command for the operator's terminal.
108+
109+
External runners do not heartbeat through Crabbox and do not participate in
110+
Crabbox lease expiry, cleanup, or cost accounting. The detail page exists so
111+
operators have a single URL to share when an external runner is stuck.
112+
113+
## Authentication And Scope
114+
115+
```text
116+
session authenticated GitHub user (owner/org embedded)
117+
admin portal sessions with the admin token role
118+
```
119+
120+
Per-route scope rules:
121+
122+
- Lease index, lease detail, run detail: own leases/runs only.
123+
- Admin filters and external runner visibility: admin sessions only.
124+
- VNC and code bridges: only when the lease has the matching capability and
125+
the session owns the lease.
126+
127+
Tokens for `/v1/...` API calls are separate. The portal never echoes a
128+
bearer token back to the browser.
129+
130+
## Why Server-Rendered
131+
132+
The portal is intentionally a thin server-rendered surface, not a SPA:
133+
134+
- the Worker already owns lease and run data; rendering at the edge avoids a
135+
separate API/UI deployment;
136+
- pages stay copy-pasteable - URLs deep-link to a specific lease or run;
137+
- there is no build step, no JavaScript framework, and no offline session
138+
management to maintain;
139+
- the portal cannot drift from the API because both serve the same Durable
140+
Object state.
141+
142+
Adding a portal feature usually means a new render in `worker/src/portal.ts`,
143+
a new endpoint in `worker/src/fleet.ts`, and a doc update here.
144+
145+
Related docs:
146+
147+
- [Coordinator](coordinator.md)
148+
- [Broker auth and routing](broker-auth-routing.md)
149+
- [History and logs](history-logs.md)
150+
- [Telemetry](telemetry.md)
151+
- [Interactive desktop and VNC](interactive-desktop-vnc.md)
152+
- [Source map](../source-map.md)

0 commit comments

Comments
 (0)