Request context

The table

What mounts these is the Worker contract, what contributes them is a capability, adding a route is where you first read one, and c.error is errors.

c.var.TypeUncomposed value
auth`AuthContextnull`
locale`LocaleContextnull`
tTranslatorA real translator over baked English
controlPlane`ControlPlaneContextnull`
controlPlaneVerifier`ControlPlaneVerifiernull`
sameOrigin`SameOriginGatenull`
emitAuditEmitA no-op recorder
entitlementsEntitlementResolverA resolver that holds nothing — so every gate 403s
logLoggerA real per-request logger
dbThe D1 registry
kvThe KV registry
workflowsThe job dispatcher

Three are zero-config, and nothing null-checks them

t, log and emit.

With no i18n composed, t is a translator over the baked English every composed capability contributed — which is why a project that never opts in behaves byte for byte as it did before.

With no audit composed, emit is a no-op. Non-fatal by contract — it never throws, so an audited action is never broken by an audit write.

One default denies, and that is the exception

entitlements.

A missing audit write cannot grant access. A missing entitlement check can.

So with no provider composed the resolver holds nothing and every gate answers 403, rather than passing because the thing meant to check it is absent.

The same reasoning makes controlPlaneVerifier null rather than permissive: that null is what makes a capability’s admin routes deny in a Worker that never enabled the seam.

auth and controlPlane are two seams on purpose

A management client is not a user of your app. It holds no session and owns no user row.

locale versus t

Read t to render a string. Read locale when you need the tags themselves — lang and dir on a document, or the locale stamped onto an email job’s row.

null means nothing was negotiated, which is a different fact from the default was chosen.

LocaleContext carries three: the catalog locale (which falls back), the formatting locale (which does not), and the direction.

sameOrigin is published already bound

Bound to this Worker’s trusted origins by the capability that resolved them. Read it through requireSameOrigin(), which takes no argument.

A bound gate rather than the origin list, deliberately. Handing over the list is how a Worker ends up with two same-origin implementations free to disagree — and the weaker one is then its real policy.

log carries what a client must not see

It carries PithyError detail — the inverse of what the HTTP codec does.

Never wire it to a client surface.

Derive a namespaced child with c.var.log.child("<capability>"). Every record already carries request correlation — the request id, method, path, environment and version.

db, kv and workflows are loosely typed on the base seam

Deliberately — the precise types depend on which capabilities are composed, and createBackend’s return narrows all three.

Inside a capability, cast to the registry your schema names.

c.var.db.app          // your database
c.var.kv.sessions     // your namespace
c.var.workflows.trigger("media/image-to-text", { id })

None of them needs a conditional

An uncomposed seam is present and inert, not absent.

c.var.emit(...) from a project with no audit capability is a call that does nothing — not a crash, and not a branch you have to write.

ESC