Skip to content

Commit 8c8300e

Browse files
Document namespace auth and worker registration
Document namespace auth worker registration
1 parent 3e7e7b0 commit 8c8300e

9 files changed

Lines changed: 297 additions & 3 deletions
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
---
2+
sidebar_position: 4
3+
title: Namespace, Auth, And Worker Registration
4+
description: Reference for server namespace resolution, role-scoped authentication, and worker registration contracts.
5+
tags:
6+
- server
7+
- namespaces
8+
- authentication
9+
- worker-protocol
10+
keywords:
11+
- Durable Workflow namespace auth
12+
- role scoped server tokens
13+
- worker registration contract
14+
- X-Namespace
15+
---
16+
17+
# Namespace, Auth, And Worker Registration
18+
19+
Use this reference when provisioning a standalone server, issuing automation
20+
credentials, or implementing a worker runtime. The server has three separate
21+
contracts that must line up before work can flow:
22+
23+
- the request names a namespace through `X-Namespace`, `?namespace=`, or the
24+
server default namespace
25+
- the credential has the role required by the route family
26+
- workers register the same namespace, task queue, runtime, type keys, and
27+
capacity that workflow starts and task polls use
28+
29+
## Request Authority
30+
31+
Durable Workflow treats namespace, auth role, and protocol version as request
32+
authority. Do not infer them from workflow ids, task ids, or display labels.
33+
34+
| Request family | Required credential role | Required version header | Namespace source |
35+
| --- | --- | --- | --- |
36+
| Discovery `GET /api/cluster/info` | `worker`, `operator`, or `admin` | none | optional `X-Namespace` for context |
37+
| Namespace list/describe | `operator` or `admin` | `X-Durable-Workflow-Control-Plane-Version: 2` | route target or request context |
38+
| Namespace create/update/storage policy | `admin` | `X-Durable-Workflow-Control-Plane-Version: 2` | route target or request body |
39+
| Workflow, schedule, task queue, bridge adapter, worker visibility | `operator` or `admin` | `X-Durable-Workflow-Control-Plane-Version: 2` | `X-Namespace`, `?namespace=`, then default |
40+
| System passes and storage tests | `admin` | `X-Durable-Workflow-Control-Plane-Version: 2` | `X-Namespace`, `?namespace=`, then default |
41+
| Worker registration, polling, heartbeats, completion | `worker` | `X-Durable-Workflow-Protocol-Version: 1.0` | `X-Namespace`, `?namespace=`, then default |
42+
43+
The server checks the route role before namespace existence on role-gated
44+
endpoints. A wrong-role token receives an auth failure instead of a namespace
45+
existence signal. After the role and version checks pass, namespace-scoped
46+
routes reject unknown namespaces with `reason: "namespace_not_found"`.
47+
48+
## Auth Roles
49+
50+
Token auth is the default production path:
51+
52+
```bash
53+
DW_AUTH_DRIVER=token
54+
DW_WORKER_TOKEN=worker-secret
55+
DW_OPERATOR_TOKEN=operator-secret
56+
DW_ADMIN_TOKEN=admin-secret
57+
```
58+
59+
If a deployment uses one shared `DW_AUTH_TOKEN`, that token effectively has all
60+
route permissions. Prefer role-scoped tokens for production so a worker process
61+
cannot mutate namespaces or run system maintenance passes.
62+
63+
The same role split exists for signature auth:
64+
65+
```bash
66+
DW_AUTH_DRIVER=signature
67+
DW_WORKER_SIGNATURE_KEY=worker-signature-secret
68+
DW_OPERATOR_SIGNATURE_KEY=operator-signature-secret
69+
DW_ADMIN_SIGNATURE_KEY=admin-signature-secret
70+
```
71+
72+
`DW_AUTH_DRIVER=none` is for local development only. It removes the auth
73+
boundary from every route and should never be exposed outside a trusted local
74+
network.
75+
76+
## Namespace Contract
77+
78+
The bootstrap process seeds the default namespace. Set
79+
`DW_DEFAULT_NAMESPACE` when omitted namespace headers should resolve somewhere
80+
other than `default`:
81+
82+
```bash
83+
DW_DEFAULT_NAMESPACE=default
84+
```
85+
86+
Create every tenant or environment namespace before directing clients or
87+
workers at it:
88+
89+
```bash
90+
curl -sS -X POST "$DURABLE_WORKFLOW_SERVER_URL/api/namespaces" \
91+
-H "Authorization: Bearer $DW_ADMIN_TOKEN" \
92+
-H "X-Durable-Workflow-Control-Plane-Version: 2" \
93+
-H "Content-Type: application/json" \
94+
-d '{
95+
"name": "orders-prod",
96+
"description": "production order workflows",
97+
"retention_days": 90
98+
}'
99+
```
100+
101+
Namespace names are normalized to lowercase and may contain letters, numbers,
102+
dot, underscore, and dash. They are unique after normalization. For example,
103+
creating `Production` and then `production` is a conflict with
104+
`reason: "namespace_already_exists"`.
105+
106+
A normal workflow start names the namespace with `X-Namespace`:
107+
108+
```bash
109+
curl -sS -X POST "$DURABLE_WORKFLOW_SERVER_URL/api/workflows" \
110+
-H "Authorization: Bearer $DW_OPERATOR_TOKEN" \
111+
-H "X-Namespace: orders-prod" \
112+
-H "X-Durable-Workflow-Control-Plane-Version: 2" \
113+
-H "Content-Type: application/json" \
114+
-d '{
115+
"workflow_type": "orders.fulfillment",
116+
"workflow_id": "order-1001",
117+
"task_queue": "orders",
118+
"input": ["order-1001"]
119+
}'
120+
```
121+
122+
Control-plane reads, workflow commands, schedule operations, search-attribute
123+
operations, task-queue visibility, and worker visibility use that same
124+
namespace context. Namespace administration routes themselves are the
125+
exception: they target the namespace in the route or request body and do not
126+
require that namespace to already exist before create or describe can run.
127+
128+
## Worker Registration Contract
129+
130+
Every worker process must register before polling. Registration is namespaced,
131+
so the tuple `(namespace, worker_id)` identifies the worker record. The
132+
registered `task_queue` must match future poll requests for that worker id.
133+
134+
```bash
135+
curl -sS -X POST "$DURABLE_WORKFLOW_SERVER_URL/api/worker/register" \
136+
-H "Authorization: Bearer $DW_WORKER_TOKEN" \
137+
-H "X-Namespace: orders-prod" \
138+
-H "X-Durable-Workflow-Protocol-Version: 1.0" \
139+
-H "Content-Type: application/json" \
140+
-d '{
141+
"worker_id": "py-orders-1",
142+
"task_queue": "orders",
143+
"runtime": "python",
144+
"sdk_version": "0.2.0",
145+
"build_id": "orders-worker-2026-04-22",
146+
"supported_workflow_types": ["orders.fulfillment"],
147+
"workflow_definition_fingerprints": {
148+
"orders.fulfillment": "sha256:definition-fingerprint"
149+
},
150+
"supported_activity_types": ["payments.capture"],
151+
"max_concurrent_workflow_tasks": 10,
152+
"max_concurrent_activity_tasks": 50
153+
}'
154+
```
155+
156+
| Field | Required | Contract |
157+
| --- | --- | --- |
158+
| `worker_id` | no | Stable process identity. The server generates one when omitted, but long-running runtimes should set it for logs and task queue diagnostics. |
159+
| `task_queue` | yes | Queue this worker polls. Poll requests for a different queue fail with `reason: "task_queue_mismatch"`. |
160+
| `runtime` | yes | One of `php`, `python`, `typescript`, `go`, or `java`. |
161+
| `sdk_version` | no | Runtime SDK version shown in worker visibility and diagnostics. |
162+
| `build_id` | no | Deploy/build identity used by task queue build-id visibility. |
163+
| `supported_workflow_types` | no | Workflow type keys this worker can replay. Empty means no workflow-type filter. |
164+
| `workflow_definition_fingerprints` | no | Per-workflow deterministic definition fingerprints. Active re-registration with a changed fingerprint is rejected. |
165+
| `supported_activity_types` | no | Activity type keys this worker can execute. Empty means no activity-type filter. |
166+
| `max_concurrent_workflow_tasks` | no | Advertised local workflow-task slots. Defaults to `100`; minimum `1`. |
167+
| `max_concurrent_activity_tasks` | no | Advertised local activity-task slots. Defaults to `100`; minimum `1`. |
168+
169+
Active re-registration with the same worker id is allowed when the advertised
170+
definition fingerprints are unchanged. If a running worker changes workflow
171+
code for an already advertised type, it must restart with a new `worker_id`;
172+
otherwise registration fails with `reason: "workflow_definition_changed"`.
173+
174+
## Polling And Visibility
175+
176+
Worker poll requests must use the same namespace, worker id, and task queue
177+
that registration used:
178+
179+
```bash
180+
curl -sS -X POST "$DURABLE_WORKFLOW_SERVER_URL/api/worker/workflow-tasks/poll" \
181+
-H "Authorization: Bearer $DW_WORKER_TOKEN" \
182+
-H "X-Namespace: orders-prod" \
183+
-H "X-Durable-Workflow-Protocol-Version: 1.0" \
184+
-H "Content-Type: application/json" \
185+
-d '{
186+
"worker_id": "py-orders-1",
187+
"task_queue": "orders",
188+
"timeout_seconds": 30
189+
}'
190+
```
191+
192+
Operators can inspect the same registration state through control-plane
193+
visibility:
194+
195+
```bash
196+
curl -sS "$DURABLE_WORKFLOW_SERVER_URL/api/task-queues/orders" \
197+
-H "Authorization: Bearer $DW_OPERATOR_TOKEN" \
198+
-H "X-Namespace: orders-prod" \
199+
-H "X-Durable-Workflow-Control-Plane-Version: 2" | jq '.pollers, .admission'
200+
```
201+
202+
Task queue visibility is the first place to check when workers receive no
203+
tasks. It distinguishes missing workers from queue mismatches, unsupported
204+
workflow/activity type filters, saturated worker slots, server active-lease
205+
caps, dispatch-rate caps, and query-task backpressure.
206+
207+
## Error Surface
208+
209+
Automation should branch on named reasons rather than prose messages.
210+
211+
| Reason | Where | Meaning | Operator action |
212+
| --- | --- | --- | --- |
213+
| `missing_control_plane_version` | control-plane route | The request omitted `X-Durable-Workflow-Control-Plane-Version: 2`. | Add the version header or upgrade the client profile. |
214+
| `missing_protocol_version` | worker route | The request omitted `X-Durable-Workflow-Protocol-Version: 1.0`. | Fix the worker client or SDK version negotiation. |
215+
| `namespace_not_found` | namespace-scoped route | The namespace from `X-Namespace`, query string, or server default does not exist. | Create the namespace or correct the client namespace. |
216+
| `namespace_already_exists` | `POST /api/namespaces` | A normalized namespace name already exists. | Reuse it or choose a distinct name. |
217+
| `task_queue_mismatch` | worker poll route | A worker id registered for one queue attempted to poll another. | Restart with a new worker id or poll the registered queue. |
218+
| `workflow_definition_changed` | `POST /api/worker/register` | Active worker id tried to advertise changed workflow fingerprints. | Restart the changed process with a new worker id. |
219+
| `validation_failed` | any JSON route | A field is missing, malformed, too large, or outside allowed bounds. | Read `errors` or `validation_errors` and correct the payload. |
220+
221+
## See Also
222+
223+
- [Server API Reference](/docs/2.0/polyglot/server-api-reference)
224+
- [Worker Protocol](/docs/2.0/polyglot/worker-protocol)
225+
- [Task Queue Admission](/docs/2.0/polyglot/task-queue-admission)
226+
- [CLI Command Reference](/docs/2.0/polyglot/cli-reference)

docs/polyglot/server-api-reference.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ filesystem path. Object-storage policies such as `s3`, `gcs`, and `azure` use
158158
an explicitly configured filesystem disk and bucket/prefix settings on the
159159
server.
160160

161+
For the full request-authority contract, including namespace resolution,
162+
role-scoped credentials, and worker registration fields, see
163+
[Namespace, Auth, And Worker Registration](/docs/2.0/polyglot/namespace-auth-workers).
164+
161165
## Bridge Adapters
162166

163167
Bridge adapters are bounded ingress endpoints. They do not execute workflow
@@ -302,6 +306,7 @@ operation details into the nested `control_plane` object.
302306
## See Also
303307

304308
- [Server guide](/docs/2.0/polyglot/server)
309+
- [Namespace, Auth, And Worker Registration](/docs/2.0/polyglot/namespace-auth-workers)
305310
- [Worker Protocol](/docs/2.0/polyglot/worker-protocol)
306311
- [Task Queue Admission](/docs/2.0/polyglot/task-queue-admission)
307312
- [External Execution](/docs/2.0/polyglot/external-execution)

docs/polyglot/server.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,9 @@ Key field notes for client code:
315315
## Connecting Workers
316316

317317
Workers poll the server for tasks and execute workflow code or activities. See the [Worker Protocol](/docs/2.0/polyglot/worker-protocol) reference for the full API contract.
318+
For the route role matrix, namespace lookup rules, and exact worker
319+
registration payload, see
320+
[Namespace, Auth, And Worker Registration](/docs/2.0/polyglot/namespace-auth-workers).
318321

319322
### PHP Workers
320323

docs/polyglot/worker-protocol.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ Read these fields before sending optional command fields:
4848
- `query_tasks`: server-routed workflow query tasks for external runtimes.
4949
- `non_retryable_failures`: workflow and activity failure metadata support.
5050

51+
Before polling, each worker must register its namespace, task queue, runtime,
52+
supported type keys, and local capacity through `POST /api/worker/register`.
53+
The [Namespace, Auth, And Worker Registration](/docs/2.0/polyglot/namespace-auth-workers)
54+
reference freezes that registration payload and the role-scoped auth contract.
55+
5156
## Workflow Task Bridge
5257

5358
The `WorkflowTaskBridge` contract defines how an external worker interacts with durable workflow tasks:

docs/search-and-navigation.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ common phrases to the smallest useful guide.
3333
| `CLI`, `dw command`, `json output` | [CLI](./polyglot/cli.mdx) | [CLI Command Reference](./polyglot/cli-reference.md) |
3434
| `Python`, `SDK`, `polyglot` | [Python SDK](./polyglot/python.md) | [CLI and Python Parity](./polyglot/cli-python-parity.md) |
3535
| `server mode`, `HTTP API`, `control plane` | [Server](./polyglot/server.md) | [Embedded to Server Migration](./polyglot/embedded-to-server.md) |
36+
| `namespace`, `auth`, `worker registration` | [Namespace, Auth, And Worker Registration](./polyglot/namespace-auth-workers.md) | [Server API Reference](./polyglot/server-api-reference.md), [Worker Protocol](./polyglot/worker-protocol.md) |
3637
| `worker protocol`, `external worker`, `heartbeats` | [Worker Protocol](./polyglot/worker-protocol.md) | [External Execution Surface](./polyglot/external-execution.md) |
3738
| `task queue`, `rate limit`, `admission` | [Task Queue Admission](./polyglot/task-queue-admission.md) | [Monitoring](./monitoring.md) |
3839
| `MCP`, `AI client`, `llms.txt` | [MCP Workflow Surface](./mcp-workflows.md) | [AI-Assisted Development](./ai-assisted-development.md), [Sample App](./sample-app.md) |
@@ -64,6 +65,9 @@ future edits cannot silently drop the route.
6465
external execution, reliability, and AI automation work.
6566
- [CLI Command Reference](./polyglot/cli-reference.md) is the command lookup
6667
page for scripts, CI, and agents.
68+
- [Namespace, Auth, And Worker Registration](./polyglot/namespace-auth-workers.md)
69+
is the request-authority reference for server namespaces, role-scoped
70+
credentials, and worker registration.
6771
- [AI-Assisted Development](./ai-assisted-development.md) lists the v2 LLM
6872
manifests, MCP tools, CLI contracts, Waterline facts, and SDK surfaces that
6973
automation should use instead of guessing from screenshots.

docs/topics.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ the sample app. The links below group those surfaces by job.
4040
## Control Plane And Polyglot
4141

4242
- [Server](./polyglot/server.md) - use the standalone HTTP control plane.
43+
- [Server API Reference](./polyglot/server-api-reference.md) - call exact HTTP control-plane and worker-plane routes.
44+
- [Namespace, Auth, And Worker Registration](./polyglot/namespace-auth-workers.md) - align namespace headers, role-scoped credentials, and worker registration.
4345
- [Embedded to Server Migration](./polyglot/embedded-to-server.md) - move from Laravel-embedded execution to server mode.
4446
- [CLI](./polyglot/cli.mdx) - install and configure `dw`.
4547
- [CLI Command Reference](./polyglot/cli-reference.md) - script exact command shapes and output modes.

scripts/discoverability-contract.json

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"title": "Control Plane And Polyglot",
2626
"links": [
2727
"polyglot/server.md",
28+
"polyglot/namespace-auth-workers.md",
2829
"polyglot/embedded-to-server.md",
2930
"polyglot/cli.mdx",
3031
"polyglot/cli-reference.md",
@@ -104,7 +105,15 @@
104105
"source": "polyglot/worker-protocol.md",
105106
"links": [
106107
"polyglot/external-execution.md",
107-
"polyglot/server.md"
108+
"polyglot/server.md",
109+
"polyglot/namespace-auth-workers.md"
110+
]
111+
},
112+
{
113+
"source": "polyglot/server-api-reference.md",
114+
"links": [
115+
"polyglot/namespace-auth-workers.md",
116+
"polyglot/worker-protocol.md"
108117
]
109118
}
110119
],
@@ -114,6 +123,7 @@
114123
"agent-tooling-contract.md",
115124
"polyglot/cli-reference.md",
116125
"polyglot/cli-python-parity.md",
126+
"polyglot/namespace-auth-workers.md",
117127
"polyglot/external-execution.md",
118128
"agent-operating-loop.md",
119129
"sample-app.md"
@@ -157,13 +167,19 @@
157167
{
158168
"query": "server mode http api control plane",
159169
"target": "polyglot/server.md",
160-
"related": ["polyglot/embedded-to-server.md"],
170+
"related": ["polyglot/embedded-to-server.md", "polyglot/namespace-auth-workers.md"],
161171
"aliases": ["standalone server", "HTTP", "control-plane"]
162172
},
173+
{
174+
"query": "namespace auth worker registration",
175+
"target": "polyglot/namespace-auth-workers.md",
176+
"related": ["polyglot/server-api-reference.md", "polyglot/worker-protocol.md"],
177+
"aliases": ["X-Namespace", "DW_WORKER_TOKEN", "worker_id", "task_queue"]
178+
},
163179
{
164180
"query": "worker protocol external worker heartbeats",
165181
"target": "polyglot/worker-protocol.md",
166-
"related": ["polyglot/external-execution.md"],
182+
"related": ["polyglot/external-execution.md", "polyglot/namespace-auth-workers.md"],
167183
"aliases": ["polling", "leasing", "heartbeats"]
168184
},
169185
{

scripts/reference-docs-contract.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,38 @@
9393
"/api/system/retention/pass"
9494
]
9595
},
96+
{
97+
"path": "polyglot/namespace-auth-workers.md",
98+
"title": "Namespace, Auth, And Worker Registration",
99+
"minimumCodeFences": 6,
100+
"requiredHeadings": [
101+
"Request Authority",
102+
"Auth Roles",
103+
"Namespace Contract",
104+
"Worker Registration Contract",
105+
"Polling And Visibility",
106+
"Error Surface"
107+
],
108+
"requiredTerms": [
109+
"DW_WORKER_TOKEN",
110+
"DW_OPERATOR_TOKEN",
111+
"DW_ADMIN_TOKEN",
112+
"X-Namespace",
113+
"X-Durable-Workflow-Control-Plane-Version: 2",
114+
"X-Durable-Workflow-Protocol-Version: 1.0",
115+
"reason: \"namespace_not_found\"",
116+
"reason: \"workflow_definition_changed\"",
117+
"reason: \"task_queue_mismatch\""
118+
],
119+
"requiredEndpoints": [
120+
"/api/cluster/info",
121+
"/api/namespaces",
122+
"/api/workflows",
123+
"/api/worker/register",
124+
"/api/worker/workflow-tasks/poll",
125+
"/api/task-queues/orders"
126+
]
127+
},
96128
{
97129
"path": "polyglot/cli-reference.md",
98130
"title": "CLI Command Reference",

sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ const sidebars = {
125125
items: [
126126
'polyglot/server',
127127
'polyglot/server-api-reference',
128+
'polyglot/namespace-auth-workers',
128129
'polyglot/embedded-to-server',
129130
'polyglot/cli',
130131
'polyglot/cli-reference',

0 commit comments

Comments
 (0)