You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Offer a hosted Wasteland service on the Kilo platform. Users can create, manage, and participate in Wastelands with a Kilo-native UI and per-wasteland infrastructure that sleeps when not in use.
Revised 2026-03-31 (v4): Simplified architecture. We build our own UI and container image rather than deploying the Wasteland's hosted Go server. No @nangohq/frontend dependency, no cookie bridging, no SPA routing issues. Per-wasteland containers (like towns), not multi-tenant.
Architecture
We build a Kilo-native Wasteland service — our own UI, our own Worker, our own Container image. The Container includes the wl CLI binary for Wasteland protocol operations (browse, claim, done, sync, post). The wl CLI handles the DoltHub fork-push-PR cycle. We do NOT run wl serve --hosted.
Browser (Kilo Next.js app)
↓ standard Kilo JWT auth
Cloudflare Worker (wasteland-proxy)
├── tRPC or REST API for wasteland management
├── Kilo auth (JWT validation, org membership)
├── Billing metering
└── Forwards protocol operations to Container
↓
WastelandDO (Durable Object — one per wasteland)
├── Wasteland metadata (name, owner, org, visibility)
├── Member list + credential storage (encrypted DoltHub tokens)
├── Cached wanted board state (polled from DoltHub)
└── Alarm loop for periodic sync
↓
WastelandContainerDO (Container — one per wasteland, sleeps when idle)
├── `wl` CLI binary (~50MB)
├── Pre-configured: `wl join` during onboarding
├── Protocol operations: `wl browse`, `wl claim`, `wl done`, `wl post`, `wl sync`
├── Env: DOLTHUB_TOKEN (from WastelandDO credential store)
└── sleepAfter: 30m (sleeps when wasteland is not in use)
Why NOT wl serve --hosted
The previous versions of this issue proposed running the Wasteland's hosted Go server. We're not doing that because:
We build better UI — our Next.js app with Kilo's design system is a better experience than the embedded React SPA
No Nango dependency — the hosted mode uses @nangohq/frontend in the browser which we'd need to fork. Instead, we store DoltHub tokens ourselves.
Per-wasteland containers — the hosted mode is multi-tenant (one process for all wastelands, never sleeps). We want per-wasteland containers that sleep when idle, matching the Gastown town pattern.
Simpler credential model — users provide DoltHub tokens in our settings UI. We store them encrypted in the WastelandDO. No Nango, no OAuth delegation, no session cookies.
The wl CLI is the only Wasteland binary we need. It handles the DoltHub protocol (fork, push, PR, sync) without running a server.
Container Image
Build our own container image with the wl CLI:
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y curl git ca-certificates jq && rm -rf /var/lib/apt/lists/*
# Install Wasteland CLI (remote mode — no Dolt needed)RUN curl -fsSL https://github.com/gastownhall/wasteland/releases/download/v0.3.0/wasteland_0.3.0_linux_amd64.tar.gz | tar xz -C /usr/local/bin/
# Lightweight control server for receiving commands from the WastelandDOCOPY control-server /app/control-server
CMD ["/app/control-server"]
The control server is a small HTTP server (~200 lines) that receives commands from the WastelandDO and executes wl CLI commands:
POST /wl/browse → wl browse --json
POST /wl/claim → wl claim <id>
POST /wl/done → wl done <id> --evidence <url>
POST /wl/post → wl post --title ... --description ...
POST /wl/sync → wl sync
POST /wl/join → wl join <upstream>
POST /wl/status → wl status <id>
GET /health → check wl + dolt availability
Container Lifecycle
Per-wasteland: One WastelandContainerDO per wasteland (same pattern as TownContainerDO)
sleepAfter: 30m: Container sleeps when not in use. Wakes on next API call.
Cold start: wl CLI needs a configured local clone. On first start (or after eviction): run wl join <upstream> to set up. Cache in the Container's ephemeral disk. Re-join on eviction (~10-30s).
State on disk: ~/.config/wasteland/ (wl config) + ~/.local/share/wasteland/<upstream>/ (local Dolt clone). Ephemeral — reconstructed from DoltHub on cold start.
Coding Conventions
Copy cloudflare-gastown/AGENTS.md to cloudflare-wasteland/AGENTS.md as the starting point for coding conventions. The gastown AGENTS.md covers file naming, Durable Object patterns (sub-modules, import * as X), IO boundary validation (Zod), column naming (entity_id), SQL query patterns (type-safe query() helper, table interpolators), and HTTP route conventions (Hono, handler modules). All of these apply equally to the wasteland service.
Credential Storage
No Nango. DoltHub tokens stored encrypted in the WastelandDO:
// WastelandDO SQLitetypeWastelandCredential={user_id: string;// Kilo user IDdolthub_token: string;// Encrypted DoltHub API tokenrig_handle: string;// User's rig handle on this wastelanddolthub_org: string;// User's DoltHub org (for fork)connected_at: string;};
When executing wl commands in the Container, the WastelandDO:
Resolves the user's encrypted token from its SQLite
Decrypts it
Passes it to the Container as a request header or env var for the specific operation
The Container's control server injects DOLTHUB_TOKEN for each wl CLI invocation.
UI (Kilo-native)
Built in the Kilo Next.js app, not the Wasteland's embedded SPA.
Pages
/gastown/wastelands — list user's wastelands (personal)
Completions — published completions and their validation status
Members — rig registry, invite, manage trust levels
Settings — name, visibility, DoltHub connection, danger zone
Design
Follow the Gastown town UI design language: dark surfaces, information-dense cards, same typography and color system. The wanted board should feel like the bead list in a town — compact cards with status pills, priority indicators, and type badges.
Authorization Model
Ownership
Same model as Gastown towns:
typeWastelandOwnership=|{type: 'user';userId: string}// Personal wasteland|{type: 'org';orgId: string}// Org-owned wasteland
Access Resolution
Follow the resolveTownOwnership pattern (router.ts:141-188):
Org members (except billing_manager) auto-granted access
Org admins registered as trust_level 3 maintainers on the commons
Cross-org: Org A's town can participate in Org B's wasteland if the user is a member of both
Wasteland Creation Flow
Creating a new wasteland requires initializing the Dolt database with the v1.2 schema. Two options:
Option A: Template fork (recommended)
Pre-create a template wasteland on DoltHub (kilo-wastelands/wl-template) with the v1.2 schema. Creating a new wasteland = fork this template via the DoltHub REST API. Instant (pointer-based fork).
Option B: CLI initialization
Run wl create in the Container, which uses dolt to init the schema locally and push to DoltHub. Takes 10-30 seconds.
Recommendation: Option A. The fork is instant and doesn't require the Container to be running during creation.
DoltHub Relationship
DoltHub API rate limits are not publicly documented. At scale, we should cultivate a partnership with the DoltHub team for:
Higher rate limits for Kilo's service account
Potentially a dedicated DoltHub instance or API tier for hosted wastelands
Schema migration coordination when the Wasteland protocol evolves
The wl CLI has a remote mode that uses the DoltHub REST API for all operations. No local Dolt clone, no Dolt binary needed. Cold start = boot Container (~3s) + wl join if needed (~2s) = ~5 seconds. No disk state beyond a tiny config file.
Hybrid: Reads from DO, Writes from Container
Read operations (browse, status, poll): Direct DoltHub SQL API calls from the WastelandDO. No Container needed. Instant, no cold start.
Write operations (claim, done, post): Via Container wl CLI. The CLI handles branch naming, PR creation, idempotency, and protocol validation.
Users can browse the wanted board instantly without waking the Container. The Container only starts when they act.
Operational Details
Control Server (~450 lines)
8 endpoints x ~40 lines + health check + token injection + serial queue + logging. TypeScript/Bun or Go.
Mutation Verification
wl claim/wl done may silently no-op (SQL WHERE matches 0 rows). The control server must re-query DoltHub after mutations to verify state change.
Container Config
instance_type: standard-2 (lighter than Gastown). max_instances: 200. sleepAfter: 30m.
Heartbeat
60s interval. Reports wl version, last operation timestamp. WastelandDO uses for crash detection.
Version Pinning
Pin wl to specific release in Dockerfile. Health check reports version. Monitor upstream releases. Rebuild on new release.
Error Handling
DoltHub down: retry with backoff, 503 to UI. Claim race: re-query, return "already claimed." Fork drift: wl sync, conflicts at PR merge time. Container eviction mid-op: retry on next tick.
Wasteland Deletion
Soft-delete in DO. Stop Container. DoltHub fork deletion not automatable (manual/orphaned). Member data retained 30 days.
Rate Limiting
Per-user: claim 10/min, done 10/min, post 5/min, browse 60/min.
Observability
wasteland_events Analytics Engine dataset. 100% Workers Observability sampling. Structured JSON logs. Health endpoint in control server.
Acceptance Criteria
Phase 1-2 (MVP)
WastelandDO with metadata + credential storage
WastelandContainerDO with per-wasteland Container lifecycle
Container image with wl CLI + Dolt + control server
sleepAfter: 30m — Container sleeps when wasteland is idle
Encrypted DoltHub token storage in WastelandDO
Template fork provisioning for new wastelands
Rig registration via wl join in Container
Wanted board polling via DoltHub REST API
resolveWastelandOwnership supporting user, org, and admin
Org members auto-granted access
Org admins registered as trust_level 3 maintainers
Summary
Offer a hosted Wasteland service on the Kilo platform. Users can create, manage, and participate in Wastelands with a Kilo-native UI and per-wasteland infrastructure that sleeps when not in use.
Architecture
We build a Kilo-native Wasteland service — our own UI, our own Worker, our own Container image. The Container includes the
wlCLI binary for Wasteland protocol operations (browse, claim, done, sync, post). ThewlCLI handles the DoltHub fork-push-PR cycle. We do NOT runwl serve --hosted.Why NOT
wl serve --hostedThe previous versions of this issue proposed running the Wasteland's hosted Go server. We're not doing that because:
@nangohq/frontendin the browser which we'd need to fork. Instead, we store DoltHub tokens ourselves.The
wlCLI is the only Wasteland binary we need. It handles the DoltHub protocol (fork, push, PR, sync) without running a server.Container Image
Build our own container image with the
wlCLI:The control server is a small HTTP server (~200 lines) that receives commands from the WastelandDO and executes
wlCLI commands:Container Lifecycle
WastelandContainerDOper wasteland (same pattern asTownContainerDO)sleepAfter: 30m: Container sleeps when not in use. Wakes on next API call.wlCLI needs a configured local clone. On first start (or after eviction): runwl join <upstream>to set up. Cache in the Container's ephemeral disk. Re-join on eviction (~10-30s).~/.config/wasteland/(wl config) +~/.local/share/wasteland/<upstream>/(local Dolt clone). Ephemeral — reconstructed from DoltHub on cold start.Coding Conventions
Copy
cloudflare-gastown/AGENTS.mdtocloudflare-wasteland/AGENTS.mdas the starting point for coding conventions. The gastown AGENTS.md covers file naming, Durable Object patterns (sub-modules,import * as X), IO boundary validation (Zod), column naming (entity_id), SQL query patterns (type-safequery()helper, table interpolators), and HTTP route conventions (Hono, handler modules). All of these apply equally to the wasteland service.Credential Storage
No Nango. DoltHub tokens stored encrypted in the WastelandDO:
When executing
wlcommands in the Container, the WastelandDO:The Container's control server injects
DOLTHUB_TOKENfor eachwlCLI invocation.UI (Kilo-native)
Built in the Kilo Next.js app, not the Wasteland's embedded SPA.
Pages
/gastown/wastelands— list user's wastelands (personal)/organizations/:orgId/gastown/wastelands— org wastelands/gastown/wastelands/new— create a new wasteland/gastown/wastelands/:wastelandId— wasteland dashboard:Design
Follow the Gastown town UI design language: dark surfaces, information-dense cards, same typography and color system. The wanted board should feel like the bead list in a town — compact cards with status pills, priority indicators, and type badges.
Authorization Model
Ownership
Same model as Gastown towns:
Access Resolution
Follow the
resolveTownOwnershippattern (router.ts:141-188):Per-Operation Authorization
Organization Support
billing_manager) auto-granted accessWasteland Creation Flow
Creating a new wasteland requires initializing the Dolt database with the v1.2 schema. Two options:
Option A: Template fork (recommended)
Pre-create a template wasteland on DoltHub (
kilo-wastelands/wl-template) with the v1.2 schema. Creating a new wasteland = fork this template via the DoltHub REST API. Instant (pointer-based fork).Option B: CLI initialization
Run
wl createin the Container, which usesdoltto init the schema locally and push to DoltHub. Takes 10-30 seconds.Recommendation: Option A. The fork is instant and doesn't require the Container to be running during creation.
DoltHub Relationship
DoltHub API rate limits are not publicly documented. At scale, we should cultivate a partnership with the DoltHub team for:
kilo-wastelands/wl-template)Implementation Plan
Phase 1: Infrastructure (Week 1)
cloudflare-wasteland/directory in the cloud monorepocloudflare-gastown/AGENTS.mdtocloudflare-wasteland/AGENTS.md(coding conventions)WastelandDO— metadata storage, credential storage, alarm loopWastelandContainerDO— per-wasteland Container classwlCLI + Dolt + lightweight control serverwlCLI commandswrangler.jsoncconfiguration (Worker + DO + Container bindings)Phase 2: Core API + Onboarding (Week 2)
createWasteland,listWastelands,deleteWasteland,getWastelandresolveWastelandOwnershipwith user, org, and admin supportwl joinin Container during onboardingPhase 3: UI + Operations (Week 3)
wlCLIPhase 4: Town Integration + Polish (Week 4)
gt_wasteland_browse, etc.) work against hosted wastelandsKey Architectural Decision: Remote Mode + Hybrid Reads
No Dolt in the Container
The
wlCLI has a remote mode that uses the DoltHub REST API for all operations. No local Dolt clone, no Dolt binary needed. Cold start = boot Container (~3s) +wl joinif needed (~2s) = ~5 seconds. No disk state beyond a tiny config file.Hybrid: Reads from DO, Writes from Container
wlCLI. The CLI handles branch naming, PR creation, idempotency, and protocol validation.Users can browse the wanted board instantly without waking the Container. The Container only starts when they act.
Operational Details
Control Server (~450 lines)
8 endpoints x ~40 lines + health check + token injection + serial queue + logging. TypeScript/Bun or Go.
Mutation Verification
wl claim/wl donemay silently no-op (SQL WHERE matches 0 rows). The control server must re-query DoltHub after mutations to verify state change.Container Config
instance_type: standard-2(lighter than Gastown).max_instances: 200.sleepAfter: 30m.Heartbeat
60s interval. Reports
wlversion, last operation timestamp. WastelandDO uses for crash detection.Version Pinning
Pin
wlto specific release in Dockerfile. Health check reports version. Monitor upstream releases. Rebuild on new release.Error Handling
DoltHub down: retry with backoff, 503 to UI. Claim race: re-query, return "already claimed." Fork drift:
wl sync, conflicts at PR merge time. Container eviction mid-op: retry on next tick.Wasteland Deletion
Soft-delete in DO. Stop Container. DoltHub fork deletion not automatable (manual/orphaned). Member data retained 30 days.
Rate Limiting
Per-user: claim 10/min, done 10/min, post 5/min, browse 60/min.
Observability
wasteland_eventsAnalytics Engine dataset. 100% Workers Observability sampling. Structured JSON logs. Health endpoint in control server.Acceptance Criteria
Phase 1-2 (MVP)
WastelandDOwith metadata + credential storageWastelandContainerDOwith per-wasteland Container lifecyclewlCLI + Dolt + control serversleepAfter: 30m— Container sleeps when wasteland is idlewl joinin ContainerresolveWastelandOwnershipsupporting user, org, and adminPhase 3-4 (Production)
References
wasteland/cmd/wl/— browse, claim, done, post, sync, join, status commandswasteland/schema/commons.sql(v1.2, 9 tables)wasteland/internal/backend/remote.go— the API our WastelandDO alarm uses for pollingcloudflare-gastown/wrangler.jsonc— per-resource Container lifecyclecloudflare-gastown/src/trpc/router.ts:141-188—resolveTownOwnership