|
| 1 | +# Nubase App Workers Reference |
| 2 | + |
| 3 | +Use this reference when shipping or managing a **full app worker** — a generated app deployed as a single Cloudflare Worker (server module + bundled static assets) onto Nubase's Workers-for-Platforms dispatch namespace, reachable at its own preview host. |
| 4 | + |
| 5 | +App workers are the **server-rendered / full-stack** deploy target. Unlike `assets_*` (static frontend only) or `functions_*` (individual edge handlers), one app worker bundles a server entry module **and** its client `dist/` into a single isolated deployment per project. |
| 6 | + |
| 7 | +## When to use which deploy target |
| 8 | + |
| 9 | +- Static frontend only (HTML/CSS/JS) → **Assets** (`assets_*`, `references/assets.md`). |
| 10 | +- A few backend handlers → **Functions** (`functions_*`, `references/functions.md`). |
| 11 | +- A whole app shipped as one server worker (SSR / API + bundled client) → **App worker** (this doc). |
| 12 | + |
| 13 | +## Deploy |
| 14 | + |
| 15 | +Deploying an app worker uploads a server bundle plus optional client assets. Because it is a multipart file upload, it runs through the CLI / deploy pipeline rather than a single MCP argument: |
| 16 | + |
| 17 | +```http |
| 18 | +POST /deployments/admin/v1/app-workers/deploy (multipart/form-data, service_role) |
| 19 | + metadata = JSON { appCode, version, workerName?, mainModule, serverEntrypointPath?, |
| 20 | + clientDistPath?, previewHost?, compatibilityDate?, compatibilityFlags?, |
| 21 | + envBindings?, plainTextBindings?, secretTextBindings? } |
| 22 | + serverFile = one or more JS module files (must include mainModule) |
| 23 | + assetFile = zero or more static asset files (served via the worker's ASSETS binding) |
| 24 | +``` |
| 25 | + |
| 26 | +- `workerName` defaults to `appCode`; `previewHost` defaults to `<workerName>.ottermind.app`. |
| 27 | +- `metadata.appCode` must match the calling project context (enforced server-side). |
| 28 | +- A custom `workerName` must equal `appCode` or be namespaced under it (`<appCode>-<suffix>`, e.g. `appabc-preview`). The dispatch namespace is shared across tenants, so a worker name outside your appCode is rejected with 403. |
| 29 | +- `NUBASE_PROJECT_REF` and `NUBASE_APP_VERSION` are injected as bindings automatically and cannot be overridden; pass app config via `plainTextBindings` and secrets via `secretTextBindings`. |
| 30 | +- The deploy is recorded in the project's deployment history (`deployments_list` / `deployment_status`). |
| 31 | + |
| 32 | +## Manage (after deploy) |
| 33 | + |
| 34 | +Management is **scoped to workers this project has deployed** — the dispatch namespace is shared across all tenants, so list/status/delete only ever resolve workers found in *this* project's deployment history. You cannot read or delete another project's worker. |
| 35 | + |
| 36 | +Read (always available): |
| 37 | + |
| 38 | +- `app_workers_list()` — list this project's deployed app workers, each with `workerName`, latest `version`, `previewHost`, `publicUrl`, `lastDeploymentStatus`, `lastDeploymentId`, and timestamps. |
| 39 | +- `app_worker_status({ workerName })` — one worker enriched with **live provider state**: returns `{ worker, existsOnProvider, provider }`, where `existsOnProvider:false` means the worker is no longer present on Cloudflare (e.g. deleted out-of-band). |
| 40 | + |
| 41 | +Write (gated by `NUBASE_ALLOW_ADMIN_WRITE=true` and the project's service_role key; otherwise returns `{ success: false, ... }` without touching the backend): |
| 42 | + |
| 43 | +- `app_worker_delete({ workerName })` — undeploy one app worker. Idempotent (deleting an already-absent worker still succeeds) and records an `app_worker_delete` entry in deployment history for audit. Returns `{ workerName, deleted, auditDeploymentId }`. |
| 44 | + |
| 45 | +Equivalent control-plane HTTP endpoints (service_role): |
| 46 | + |
| 47 | +```http |
| 48 | +GET /deployments/admin/v1/app-workers |
| 49 | +GET /deployments/admin/v1/app-workers/{workerName} |
| 50 | +DELETE /deployments/admin/v1/app-workers/{workerName} |
| 51 | +``` |
| 52 | + |
| 53 | +## Worked Example: inspect then retire a worker |
| 54 | + |
| 55 | +```text |
| 56 | +app_workers_list() |
| 57 | +# → [{ workerName: "my-app", version: "2", publicUrl: "https://my-app.ottermind.app", lastDeploymentStatus: "succeeded", ... }] |
| 58 | +
|
| 59 | +app_worker_status({ "workerName": "my-app" }) |
| 60 | +# → { worker: {...}, existsOnProvider: true, provider: { ...live Cloudflare script details... } } |
| 61 | +
|
| 62 | +app_worker_delete({ "workerName": "my-app" }) # needs NUBASE_ALLOW_ADMIN_WRITE=true + service_role |
| 63 | +# → { workerName: "my-app", deleted: true, auditDeploymentId: "..." } |
| 64 | +``` |
| 65 | + |
| 66 | +## Safety |
| 67 | + |
| 68 | +- Deleting an app worker takes the live app offline immediately — ask the user before calling `app_worker_delete`, the same as any destructive deploy op. |
| 69 | +- Never put service_role keys or other secrets in `plainTextBindings` (those are plain text) or in bundled `assetFile` contents (assets are public). Use `secretTextBindings` for secrets. |
| 70 | +- After deploying or retiring an app worker, `memory_write` the durable facts (worker name, preview host, version). |
0 commit comments