OS
OS is an authenticated app where users manage organization-owned projects and run scripts through itx capability handles. This context defines the language for project ownership, itx capabilities, streams, and project ingress.
Language#
Mention: A resource identified within a message's readable content, with metadata describing its target. The target may be a repository file, user, agent, or stream. Avoid: message reference, annotation, attachment (for mentions of existing resources), rich-text document
Mention Resolution: The recorded outcome of retrieving a Mention's target, including the source identity and any content included for the agent.
Historical note (itx-v4 cutover 2026-07 + single-worker cutover PR #1636): entries below that describe the legacy stacks — the Ingress Route Table machinery,
__null__Durable Object name encoding,/api/itx/:projectIdOrSlughandles, Workspace Durable Objects,ProjectIngressEntrypoint, Fetch Callables, and the "OS Ingress Worker" / "OS App Worker" split (OS now deploys as ONE worker) — refer to DELETED code. The engine (apps/os/src/) addresses Durable Objects viaDurableObjectNameCodec({projectId: string | null, path}), serves one capnweb surface at/api(context selection happens viaprojects.get(id)afterauthenticate()), and routes everything insrc/worker.tsvia thesrc/ingress.tsdecision. Seeapps/os/src/README.mdfor current language.
Product Ownership#
OS App: The authenticated dashboard where users manage organization-owned projects and run itx scripts. Avoid: Public site, marketing app
Organization: The owning account boundary for projects in OS. Avoid: Workspace, team, tenant, account
Active Organization: The Organization selected by auth-worker session claims for organization-level UI and project creation. Avoid: Current workspace, selected account
Personal Account: The auth worker's non-organization user context, which OS does not allow for project ownership. Avoid: Personal organization, default organization
User: A person authenticated by the auth worker who acts inside an Organization. Avoid: Member, account
OAuth Access Token: An auth-worker-issued OAuth access token used by a remote MCP client to call OS as a protected resource. Avoid: MCP JWT, session token
Principal: The request-local authenticated actor resolved by OS from the admin API secret, auth-worker session cookie, or auth-worker OAuth access token. Avoid: Raw auth payload, token claims, provider-specific auth object
Admin API Secret: The shared secret that grants OS operator automation full app-level authority. Avoid: Admin user, admin session, root user
Capability Scope: The authority boundary derived from a Principal that determines which OS capabilities can be reached. Avoid: Tenant context, organization context, permission bag
Project: An OS-managed app surface owned by exactly one Organization. Avoid: App, site, workspace
Data Scope: The ownership boundary for a persisted OS record: Project, Organization, User, or Global. Avoid: Tenant type, resource kind
ID: A stable TypeID-prefixed identifier for a durable domain object (project ids are minted by the auth worker; everything else by the engine). Avoid: slug, key, database rowid
Slug: A human-readable locator constrained to hostname-safe lowercase letters, numbers, and hyphens. Avoid: ID, arbitrary key
Key: An arbitrary string locator chosen by a caller or integration for project-local lookup. Avoid: ID, slug, hostname label
Project ID: The stable TypeID-prefixed OS identifier for a Project. Avoid: Project slug, Project Route
Project Slug: The globally unique hostname-safe Slug used in Project Routes. Avoid: Project ID
Project Route:
The dashboard URL for a Project, identified by Project slug under
/projects/:projectSlug.
Avoid: Organization-scoped project URL, project ID URL
Project Route Context: The TanStack Router route context for a Project Route. It should resolve the pretty Project Slug into the Project row once so child routes can render with Project details and call project-scoped APIs with either slug or ID. Avoid: Assuming inherited project data, page-local project state
Project-Scoped itx Handle:
An itx handle narrowed to one authorized Project. External callers select a
project by slug or stable ID at /api/itx/:projectIdOrSlug; the resolved
handle operates in that Project's capability scope.
Avoid: Raw projectId handler, unchecked project route
Project Durable Object Namespace: The Worker environment binding used by server code to obtain Project Durable Object stubs. Avoid: project context, resolved project
Durable Object Name:
The canonical OS Durable Object identity string, encoded as ${projectId ?? "__null__"}:${path} from required object-form { projectId, path }.
Avoid: namespace name, JSON structured name, Durable Object catalog name
Durable Object Name Codec:
The small OS module that converts between object-form { projectId, path } names and encoded string names such as proj_123:/repos/project or __null__:/repos/project.
Avoid: domain-specific name helper, structured JSON name, namespace parser
Project MCP Route:
The OS app's normal TanStack Start MCP route at /api/mcp. The canonical OAuth
resource URL comes from APP_CONFIG_MCP__BASE_URL and may route through a
dedicated MCP hostname, but the app-host /api/mcp route is also valid. OAuth
access tokens expose projects granted by token claims and scopes; admin-token
sessions expose all projects. Project-scoped tools such as exec_typescript select the
Project per invocation.
Avoid: Project MCP hostname, ingress MCP alias
Ingress Hostname: A public hostname that OS can classify before running the OS App. Avoid: Route, URL, domain
Project-Owned Hostname: An Ingress Hostname owned by exactly one Project. Avoid: Project URL, project domain
Project Ingress Host: A rootable Project-Owned Hostname that sends requests to one Project's Project Ingress. Avoid: Project URL, route path
Slug Project Ingress Host:
The human-readable platform Project Ingress Host derived from the Project Slug, such as <project-slug>.<project-host-base>.
Avoid: Stable project host
Stable Project Ingress Host:
The immutable platform Project Ingress Host derived from the Project ID, such as <project-id>.<project-host-base>.
Avoid: Slug project host, canonical host
Project Ingress: Traffic for a Project-Owned Hostname after the OS Worker has classified it. Avoid: App route, TanStack route
Ingress Route Table: A set of ordered routing rules that match an HTTP request and resolve it to a Fetch Destination. Avoid: URL map, hostname registry
Ingress Routing Rule: One match rule inside an Ingress Route Table. Avoid: TanStack route, route handler
Exact Host Ingress Rule: An Ingress Routing Rule that matches exactly one normalized hostname. Avoid: Host pattern, path rule
Fallback Ingress Rule: A call-site supplied low-priority Ingress Routing Rule used when no more specific rule matches. Avoid: Seed route, default row
Fetch Destination: A route target that can accept an HTTP request through a fetch-shaped callable. Avoid: Handler, app route, service
Fetch Callable: The serializable route target description stored on an Ingress Routing Rule. Avoid: Callable wrapper, destination callable
OS Ingress Worker: The skinny Worker entrypoint that classifies public traffic and proxies it to Fetch Destinations. Avoid: OS App, control plane app
OS App Worker: The Worker that runs the authenticated OS App behind the OS Ingress Worker. Avoid: Ingress worker, public worker
Project Ingress Entry Point:
A named WorkerEntrypoint exported as ProjectIngressEntrypoint that receives Project identity as props, resolves the Project Durable Object, and delegates Project Ingress to it.
Avoid: Project app worker, project service
Project Egress:
Future outbound HTTP/S policy work for Project-owned execution. Current itx
fetch(...) and itx.fetch(...) calls go through the default itx Fetch
Capability; full egress policy and secret injection live in
tasks/project-egress-secrets-mvp.md.
Avoid: Project Ingress, implemented gateway, implemented secret system
Project Worker: The Project-owned dynamic Worker loaded from Project Repo code. Avoid: OS App Worker, Project Durable Object, itx worker
Project Worker Fetch:
A direct fetch call against the Project Worker, bypassing public Project Ingress classification.
Avoid: Project Ingress, Project Egress, OS App fetch
Project Egress Fetch Shadow:
A live itx-provided fetch capability that intercepts outbound Project Egress fetches while connected.
Avoid: external egress proxy, egress gateway, intercept egress traffic
Project Egress Shadow: Short form for Project Egress Fetch Shadow. Avoid: project proxy, mock internet proxy
Project Egress Shadow Session:
The itx session that provides the live fetch capability shadow.
Avoid: mock route, test-only route, proxy URL
Project Egress Intercept Test Helper:
An e2e fixture helper that provides a live fetch capability shadow for a test-owned Project.
Avoid: external proxy fixture, mock internet proxy
itx Fetch Capability:
The default Project Egress capability used for itx.fetch(...) and bare
fetch(...) inside platform-loaded itx isolates. It is shadowable through
itx.provideCapability({ name: "fetch", ... }); the default pipe is where
secret placeholders are substituted.
Avoid: Raw Dynamic Worker fetch, untraced public fetch
Secrets Capability:
The project-bound itx capability (itx.secrets) over path-addressed Secret
Durable Objects. Secrets are identified by normalized paths under /secrets/;
there is no separate secret ID or key.
Avoid: D1-backed secrets, Secret ID, Secret Key, separate secrets service
Secret Material:
The single serializable value one Secret holds — write-only, encrypted at rest
as one blob. Writes replace the whole value through the one update verb; there
are no field-level writes and no per-field metadata. Placeholder references may
select into structured material (getSecret(path, { field: "field" })), which is
read addressing, not a storage concept.
Avoid: material fields, store(), partial secret writes, per-field expiry
Secret Cell Invariant:
The one property of a Secret: material goes in; nothing comes out except a
request to a pinned host. No read lane, no reveal lane, no compute methods,
no cross-secret chaining — the Secret Durable Object's only material-touching
verb is fetch() (substitute header placeholders, dispatch under the egress
pin). Ciphertext is authenticated to its project, secret path, exact effective
origins, and storing event offset; every update without replacement material
clears it, while replacement material requires its complete egress policy in
the same update. Credential redirects are manual, bounded, and same-origin. Secret
stream facts remain user-appendable; replayed ciphertext cannot authenticate in
a different event or policy context. See ADR 0005.
Avoid: revealForPlatformUse, secret read API, hmac/sign/matches on secrets
Secret Refresh Strategy:
The named credential-refresh behavior a Secret optionally runs in its own
trusted DO code on a 401 or a missing field — oauth-refresh-token (RFC 6749
refresh grant) or github-app-installation (App-JWT mint). One shared
implementation per protocol, parameterized per secret; exchange endpoints
must fall within the Secret's own egress pin. Configuring it is the trust
event.
Avoid: secret worker, refresh worker, per-secret refresh code, refresh
convention
Platform Credential:
A deployment-owned credential (OAuth client, GitHub App key, first-party API
key) resolved from typed AppConfig by ordinary trusted code against the
closed registry in platform-secrets.ts, each entry pinned to its provider
origins. Referenced from untrusted-composed requests as
getSecret({ platform: "<configPath>" }) (API keys, resolved at the project
egress door) or from refresh strategies as { platform: "<configPath>" }.
Never a Durable Object, never project material, never readable.
Avoid: platform secret path, /secrets/platform/**, virtual secret,
revealable platform credential
OS MCP Handler:
The app worker's stateless /api/mcp handler that exposes the inbound MCP
server, verifies OAuth or admin credentials, selects the Project, and runs
tools against the Project-scoped itx context.
Avoid: Project MCP hostname, ingress MCP entrypoint, Tool Provider, Capability wrapper
Loopback Fetch Callable: A Fetch Callable that targets a named entrypoint exported by the same Worker and passes dynamic props through Cloudflare loopback bindings. Avoid: Service binding with props, local function
Project Durable Object: The authoritative runtime owner for one Project's ingress policy and project-local routing. Avoid: Project row, project API
ProjectDurableObject: The TypeScript class/export name for the Project Durable Object. Avoid: ProjectGrubbleObject, Project DO class
Project Control Surface: The RPC command surface on the Project Durable Object for managing Project lifecycle, ingress, destinations, and other project-owned state. Avoid: project service layer, app-worker lifecycle logic
Create Project Command: The Project Control Surface command that creates a Project's lifecycle state and projections. Avoid: Initialize project, create project row
Project Projection: A queryable record outside the Project Durable Object that is derived from the Project Durable Object's desired state. Avoid: Source of truth, duplicate state
Project Listing Projection:
The app-level D1 projects row used by OS to list, route to, and search Projects.
Avoid: Project source of truth, Durable Object catalog row
Durable Object Catalog: The shared mixin-owned D1 tracking table that records initialized Durable Objects for discovery and repair workflows. Avoid: Project table, application projection
Durable Object Utility Route: An infrastructure route mounted on the OS Worker entrypoint for initializing, inspecting, or listing Durable Objects through shared durable-object utilities. Avoid: Product route, TanStack route
Project Route Destination: A project-local target that a Project Durable Object can route Project Ingress to. Avoid: App, service, endpoint
Project Route Authorization: A future Project Durable Object-owned policy decision for whether a principal may access a Project Route Destination. Avoid: MCP authorization, app-specific auth method
Project Access Check: A generic Project Durable Object-owned check that decides whether an auth worker principal can access one Project. Avoid: MCP authorization, route-specific permission
Project Stream Explorer: The OS project-bound UI for discovering and inspecting every initialized Event Stream Path for one Project. Avoid: generic stream explorer, stream tree
Agents#
Agent: A project-scoped assistant work surface that users can list, open, and chat with. An Agent is identified inside one Project by an Agent Path. Avoid: Project Agent, raw stream
Agent Path: The project-local Event Stream Path that identifies one Agent within a Project. Avoid: Agent ID, Project Agent path, global path
Agent Durable Object: A project-scoped Durable Object representing one Agent. Avoid: Script Execution, Tool Provider, assistant message
AgentDurableObject: The TypeScript class/export name for the Agent Durable Object. Avoid: Subagent class, Agent DO class
createStreamProcessorHost:
The factory that hosts StreamProcessor instances inside a domain Durable Object: host.add((deps) => new SomeProcessor(deps)) registers a processor under its contract slug, and host.wakeStreamProcessor answers stream wakeups by re-subscribing from the processor's durable checkpoint.
Avoid: withStreamProcessor, host mixin, dynamic processor registry
Stream Processor keepAliveWhile:
A host-provided best-effort in-memory function that lets processor hooks keep async work alive until a promise settles.
Avoid: Durable Object ctx.waitUntil, durable scheduler, alarm-backed task
Project Lifecycle Stream:
The Project-owned root Event Stream Path / that records durable Project lifecycle facts.
Avoid: Project UI state stream, project activity log
Project Lifecycle Event: A fact appended to the Project Lifecycle Stream about Project creation, ingress, provisioning, or repair. Avoid: UI event, lifecycle command, log line
Project Lifecycle Processor: The stream processor that interprets Project Lifecycle Events and performs Project provisioning work. Avoid: Project UI reducer, project service, background job
Project Lifecycle Reduced State: The derived Project lifecycle status produced by reducing Project Lifecycle Events. Avoid: Project source of truth, frontend state, Project Projection
itx and Capabilities#
Event Stream Path:
The project-local stream address that an itx script or processor reads from
and appends to. OS stream coordinates are explicit { projectId, path }; paths
must not start with /projects/{projectId}.
Avoid: global path, Durable Object name
StreamsBackend:
A Project ID-backed RPC capability for stream operations. Its props bind stream
operations to the Project ID, and optional streamPath props narrow calls to
one project-local Event Stream Path.
Avoid: Generic stream client, cross-app stream client
ReposCapability: A Project ID-backed itx capability for creating, listing, and selecting Repos inside one Project. Avoid: Repo service, Artifact client, GitHub client
itx Handle:
The local JavaScript object handed to scripts, browser code, workers, and
external clients. It holds built-in verbs such as describe,
provideCapability, and extend, plus dotted capability calls such as
itx.integrations.slack.get().chat.postMessage(...).
Avoid: ExecutionContext, tools, legacy context tools
itx Capability:
A named callable surface visible from an itx Handle. A capability may be a live
JavaScript function or object, a Worker RPC address, or a path-call target that
implements call({ path, args }).
Avoid: Tool Provider, route, service
Capability Instructions: String-form guidance registered with an itx Capability that tells script authors how to use it. Avoid: Documentation field, function registry, route manifest
Callable Builder: A helper function that constructs a Callable descriptor for one Capability invocation shape. Avoid: Static callable, callable JSON helper, descriptor factory
Path Call:
The normalized call envelope produced by the itx path proxy for dotted calls
such as itx.mcp.exa.web_search_exa(...).
Avoid: Function Call, Tool Function Call, direct RPC call
Script Execution ID: The Script Execution correlation ID stored in itx script events. Avoid: Script ID, requested offset field
Capability Path: The registered itx path at which a capability is mounted. Avoid: Root path, namespace, provider slug
Function Path: The itx path remaining after the Capability Path has been matched. Avoid: Relative path, method path, route
Unary Capability: An itx capability whose Capability Path is itself callable and whose Function Path is empty when called. Avoid: Root tool, special function, direct callable
Stateful Capability Endpoint: A directly addressable Durable Object or Worker endpoint that executes capability calls while owning long-lived connection state. Avoid: Singleton tool, direct service, provider runtime
Outbound Capability Actor: A capability implementation that is not externally addressable and can only observe requests or report results through outbound communication. Avoid: Offline tool, browser tool, poll provider
SDK-backed Capability: An itx capability whose Function Paths are mapped to calls on an underlying SDK rather than enumerated as separate OS-owned function definitions. Avoid: Generated tool registry, SDK route table
RPC Capability: An itx capability whose implementation is reached through a Worker RPC target. Avoid: Direct tool, live provider
Live Tool Handle: A Cloudflare RPC value returned by an RPC Capability that exposes its own method surface after the original Path Call returns. Avoid: nested provider proxy, serialized data object
Repo: A project-scoped versioned file tree identified by one Project ID and one Repo Path. Avoid: Repository row, GitHub repo, Cloudflare Artifacts repo
Repo Path:
The full project-local Event Stream Path that identifies one Repo inside a Project, such as /repos/project.
Avoid: Repo slug, Repo ID, Artifact name, GitHub repo name, relative repo path
Repo Stream: The Project-owned Event Stream Path at the Repo Path that records durable Repo lifecycle facts. Avoid: Artifact log, repo activity feed, repo UI state
Repo Lifecycle Event: A fact appended to a Repo Stream about Repo creation, backing storage, or future external connections. Avoid: Git commit, Artifact API response, UI event
Repo Created Event: The Repo Lifecycle Event that records the initial project-local Repo facts needed to derive Repo state. Avoid: Create response, Artifact response, Repo row
Repo Stream Processor: The stream processor that interprets Repo Lifecycle Events and derives Repo state. Avoid: Repo service, Artifact wrapper, UI reducer
Repo Reduced State: The current Repo state derived by reducing Repo Lifecycle Events from one Repo Stream. Avoid: Repo row, Durable Object fields, frontend state
Project Repo:
The project-created Repo at Repo Path /repos/project that stores project-local Iterate configuration.
Avoid: config artifact, project settings row, GitHub config repo
Iterate Config Base Repo:
The global Repo Reference { projectId: null, path: "/repos/iterate-config-base" } that seeds each Project's Project Repo by Artifact fork.
Avoid: template row, default config object, GitHub template
Repo Reference:
An object-form reference to one Repo using { projectId, path }, where projectId: null identifies a global Repo.
Avoid: artifact name, alternate repo id, stringly repo locator
Cloudflare Artifacts: The Cloudflare-hosted Git-compatible storage service currently used as backing storage for OS Repos. Avoid: Repo, GitHub repo, Artifact repo
Repo Durable Object: An event-backed Durable Object selected by Project ID and Repo Path and exposed through itx as a live handle. Avoid: Repository row, repo provider, GitHub repo
Workspace Durable Object:
An event-sourced, mount-routed Durable Object owning one workspace's private
overlay; every project repo is mounted at its own /repos/** path by
derivation.
Avoid: Organization, Project, checkout
Workspace:
A private working copy of the project's path namespace exposed through
itx.workspace; repo mounts at /repos/**, private files under the
workspace's own path.
Avoid: Organization, Project, workspace alias
Outbound MCP From Our Client Capability: A Durable Object-backed itx capability that connects from OS to one external MCP server using our MCP client connection and exposes that remote server as itx capability paths. Avoid: inbound MCP server, MCP metadata provider, describe callable, MCP registry
OpenAPI Client Capability: A capability that exposes one OpenAPI specification as itx capability paths. Avoid: OpenAPI metadata provider, describe callable, OpenAPI registry
Script: User-authored TypeScript code that can be run by itx. Avoid: Function, tool, provider, execution
Script Execution: One attempt to run a Script against an itx Handle. Avoid: Script, execution ID, script ID
Approval Batch:
The unit of egress approval: one project/human-approval-requested event
carrying an ordered list of held requests — a Script Execution's concurrent
burst at one egress rule, coalesced at the egress door within the rule's
debounce window — decided by exactly one human-approval-decided event with
a verdict per index and at most one signature (approval.v2). A lone request
is an Approval Batch of one and renders identically to how a single request
always has.
Avoid: Approval Group, notification group
Provider Bridge: An adapter that exposes an external system, such as OpenAPI or MCP, as an itx Capability. Avoid: tool provider descriptor, session capability
Outbound MCP From Our Client Tool Provider: A Tool Provider registration whose RPC Callable targets an Outbound MCP From Our Client Capability. Avoid: Project MCP route, inbound MCP
Relationships#
- The OS App has no public product pages; unauthenticated users are sent to auth-worker sign-in.
- The OS App hides Personal Account mode and requires an Organization context.
- Every persisted OS record should have an explicit Data Scope: Project, Organization, User, or Global.
- A record's Data Scope should be represented as first-class queryable columns, not only inside JSON payloads or callable props.
- The Durable Object Catalog is infrastructure state and is separate from application-level Project Projections.
- Durable Object Utility Routes may be mounted into the OS Worker entrypoint so app code can reuse shared Durable Object initialization, catalog, and lifecycle utilities.
- An Organization owns zero or more Projects.
- A Project belongs to exactly one Organization.
- The Project Durable Object is the lifecycle authority for a Project.
- Every Project has one Project Lifecycle Stream at root Event Stream Path
/for that Project ID. - The Project Lifecycle Stream records Project Lifecycle Events as facts, not frontend view state.
- Resource streams such as
/repos/projectare child Event Stream Paths under the same Project ID. - The Project Lifecycle Processor may use Project Lifecycle Reduced State to decide follow-up work, but Project Lifecycle Events remain the shared durable facts.
- The OS frontend may reduce Project Lifecycle Events with the same reducer as the Project Lifecycle Processor, but it does not own the Project lifecycle model.
- The Project Listing Projection is derived query state and should be written by the Project Durable Object as part of Project lifecycle commands.
- A Project owns zero or more Repos.
- A Repo belongs to exactly one Project.
- A Repo is identified in OS by required
projectIdand Repo Path; Cloudflare Artifacts is backing storage, not OS domain identity. - A Repo Reference always uses
{ projectId, path }; it does not use a Repo slug or Cloudflare Artifact name. - The Iterate Config Base Repo is referenced as a global Repo Reference with
projectId: null. - A Repo Durable Object uses a canonical Durable Object Name whose path identifies the Repo inside its Project.
- Every Repo has one Repo Stream at its Repo Path for that Project ID; the Repo Path is the Repo identity, not a projection of another identifier.
- A Repo Stream records Repo Lifecycle Events as facts, not frontend view state.
- A Repo Created Event records the initial facts for one Repo and is consumed by the Repo Stream Processor.
- Repo Reduced State is derived from the Repo Stream Processor, not from ad hoc Durable Object fields or frontend state.
- The Repo Created Event payload is project-local; Project ID comes from stream coordinates, not the event payload.
- Git access tokens are minted on demand and are not part of the Repo Created Event or Repo Reduced State.
- Every new Project gets a Project Repo with Repo Path
/repos/project. - The Project Repo is forked from the Iterate Config Base Repo during Project creation and then behaves like an ordinary Repo.
- ReposCapability owns Repo collection semantics for one Project; repo dashboard routes and scripts call it through itx instead of duplicating Repo lifecycle logic.
- Creating a Repo is explicit through ReposCapability create behavior and fails if that Repo already exists.
- Selecting a missing Repo returns a not-found result and should not initialize a Repo Durable Object.
- A Key may contain characters that are not valid in a Slug; do not use a Key where OS needs hostname-safe routing.
- A Project Route includes the globally unique Project slug.
- A Project Slug is route identity and may change; a Project ID is stable identity.
- A Project Route resolves its Project Slug before rendering Project-local UI. Project-scoped itx handles accept a slug or stable Project ID at connect time and then operate on the resolved Project ID.
- The Project Slug used in the Project Route is browser-facing route identity, not stream coordinate identity.
- Every external Project-Scoped itx Handle accepts
projectIdOrSlug, resolving globally unique Project Slugs and stable Project IDs through the same project-scope access path. - A Project Durable Object Namespace is infrastructure context; a resolved and authorized Project is domain context.
- Browser routes use pretty Project Slugs in URLs and may pass either the slug or resolved stable Project ID when opening Project-scoped itx handles.
- Every Project has a Stable Project Ingress Host derived from the Project ID.
- Every Project has a Slug Project Ingress Host derived from the current Project Slug.
- The Stable Project Ingress Host remains routable even when the slug-derived host changes.
- Custom hostname, default-host, dashboard-host, and stream-host lifecycle are future ingress work, not current routing behavior.
- A Project MCP Route may expose one or more authorized Projects.
- A Project MCP Route is the app worker's
/api/mcpStart route. The canonical MCP resource URL fromAPP_CONFIG_MCP__BASE_URLcan point at a dedicated MCP hostname, and the OS app-host/api/mcproute reaches the same handler. - Project-scoped MCP tools select one Project per invocation before touching project-local capabilities.
- An Approval Batch never spans egress rules or Script Executions: the egress door coalesces only one Script Execution's concurrent requests at one rule, so mixed hold policies inside a batch are structurally impossible.
- An Approval Batch is decided as a single unit: one
human-approval-decidedevent carries a verdict per request index, and one signature (approval.v2) covers the request subjects plus the verdicts. Settlement stays per released request. - OS exposes one global MCP resource; it does not expose per-project MCP hostnames.
- The OS Worker classifies every request by Ingress Hostname before invoking the OS App.
- The OS Worker uses a global Ingress Route Table to decide whether a request becomes Project Ingress or continues to the OS App.
- Requests that do not match the global Ingress Route Table are handled by the OS App.
- Requests whose global Ingress Routing Rule resolves to a Project Durable Object are Project Ingress and are delegated to that Project's Project Durable Object.
- The Ingress Route Table is evaluated by pure matching logic over a request and a route lookup dependency.
- Ingress Routing Rules have stable unique IDs and deterministic priority ordering.
- The first concrete stored Ingress Routing Rule is an Exact Host Ingress Rule so the global lookup can compile to a simple indexed SQL query.
- Stored Ingress Routing Rules carry their target as a top-level Fetch Callable.
- Fallback Ingress Rules are provided by the caller and are not stored as seed data.
- The global Ingress Route Table stores project-owned exact-host rules, not OS App fallback routes.
- Global Ingress Routing Rules that route to a Project store Project ID as a first-class scope column as well as inside their Fetch Callable props.
- The OS App Worker is the fallback destination for every request that does not match a stored global Ingress Routing Rule.
- The OS Ingress Worker may be a separate public Worker script from the OS App Worker.
- The OS App Worker does not need its own public route when it is only reached through the OS Ingress Worker.
- The Project Durable Object stays exported from the main OS Worker for now so Loopback Fetch Callables can pass dynamic entrypoint props.
- The Project Ingress Entry Point is the public fetch-shaped bridge from a matched global ingress rule to the Project Durable Object.
- The Project Ingress Entry Point class/export name is
ProjectIngressEntrypoint. - The Project Ingress Entry Point takes only a stable Project ID prop in v1, resolves the Project Durable Object stub by using that Project ID as the Durable Object name, and delegates the request to the Project Durable Object's ingress RPC.
- The Project Ingress Entry Point does not accept Project Slug props in v1; slug-to-ID resolution happens before a request reaches hot ingress.
- Project Egress is implemented as the project-owned outbound door.
Explicit
itx.egress.fetch(...)calls and dynamic-worker barefetch(...)both route through the Project Durable Object. - A live Project Egress interceptor dispatches before Secret substitution, so
it sees
getSecret(...)references unsubstituted. Without an interceptor, Project Egress replaces allowed header Secret references before public fetch. - Project-scoped Secret CRUD goes through path-addressed Secret Durable Objects. UI and script callers must not reimplement Secret storage behavior directly.
- Project-scoped Secret reads return redacted Secret summaries and metadata, not raw Secret material.
- A Project Secret is addressed by a normalized path under
/secrets/. - Secret References resolve by path, such as
getSecret("/secrets/openai-api-key"), optionally selecting a field of structured material:getSecret("/secrets/foo", { field: "tokens.access" }). - Secret substitution is header-only, everywhere; request bodies and WebSocket frames are never scanned or substituted (ADR 0005).
- A request's headers may reference several Secrets; substitution chains through each referenced Secret's resolver, and every hop enforces its own host pin against the terminal destination.
- Platform Secret material never enters a Secret Jail; jails hold only project-tier material.
- The app worker's OS MCP Handler owns MCP protocol paths, OAuth
protected-resource metadata paths, and 404s for unsupported paths below
/api/mcp. - The Outbound MCP From Our Client Capability Durable Object class name is
OutboundMcpFromOurClientCapability. - The Outbound MCP From Our Client Capability uses the
OUTBOUND_MCP_FROM_OUR_CLIENT_CAPABILITYnamespace binding. - The app worker's OS MCP Handler owns MCP OAuth protocol verification in v1.
- The Project Durable Object must not grow MCP-specific authorization methods such as
authorizeMcpServerConnection. - The Project Durable Object may expose a generic Project Access Check in v1 for entrypoints that have already verified a principal.
- The v1 Project Access Check first trusts auth-worker project claims and may use the app-level Project Listing Projection in D1 as a legacy fallback.
- Future project-owned authorization should be modeled as generic Project Route Authorization for Project Route Destinations.
- New OS Worker named entrypoints live in an
entrypoints/source folder, separate fromdurable-objects/. - A Loopback Fetch Callable is preferred when an ingress rule needs to target a named OS Worker entrypoint with per-route props.
- The Project Durable Object exposes the Project Control Surface for project lifecycle commands.
- The Create Project Command is the domain command for creating a Project; do not call the domain command "initialize project".
- The app worker authenticates the caller, validates the requested slug, allocates the Project ID, gets the Project Durable Object by Project ID, and calls the Create Project Command.
- The Create Project Command writes the Project Durable Object's local lifecycle state and all v1 D1 projections before returning to the RPC caller.
- Asynchronous provisioning work, such as Cloudflare DNS/custom-hostname/certificate lifecycle, may continue after the Create Project Command has written durable desired state.
- TanStack project routes and itx entrypoints should thinly proxy project lifecycle commands to the Project Control Surface instead of reimplementing project lifecycle logic in the app worker.
- The Project Durable Object owns project ingress routing. MCP auth lives in the app worker's OS MCP Handler, which uses verified token claims and scopes after token verification.
- The Project Durable Object is the authority for desired project-owned ingress state.
- Global Ingress Routing Rules for project-owned hostnames are Project Projections written for fast indexed lookup by the OS Worker.
- V1 may synchronously write Project Projections from Project Control Surface commands even though Durable Object SQLite and D1 are not one atomic transaction.
- Project Ingress currently includes platform slug/stable hosts. Custom hosts and per-destination auth are future work.
- A Project Durable Object owns a project-local Ingress Route Table that maps Project Ingress to Project Route Destinations.
- A Project Route Destination is a kind of Fetch Destination.
- A Fetch Destination may be backed by OS-packaged source code, runtime-loaded code, or another project-owned capability.
- Global and project-local ingress use the same Ingress Route Table concept even though their first concrete destinations differ.
- Projects are born with Slug Project Ingress Host and Stable Project Ingress Host routes.
- Projects are not born with MCP hostname aliases; MCP access is centralized at the canonical OS MCP endpoint.
- Slug changes should update slug-derived ingress routes at the same time; alias lifecycle is future work.
- Project MCP server
exec_typescriptstarts a Script Execution and therefore requires a Script. - Browser REPL execution and Project MCP server
exec_typescriptshare the same itx script runner shape. - A Project Route resolves its Project Slug to the stable Project ID before opening a Project-Scoped itx Handle.
- A Project MCP Route resolves to the stable Project ID from token claims or the tool invocation's selected project slug before running a project-scoped script.
- A User acts through their Active Organization when managing Projects.
- A signed-in User without an Active Organization must create or select an Organization before using OS.
- A remote OAuth MCP client calls OS with an OAuth Access Token.
- First-party or e2e MCP clients should use either an OAuth Access Token or the OS admin API secret.
- A Script receives an itx Handle.
- A Script Execution is identified by
executionIdonevents.iterate.com/capability-host/script-run-requestedandevents.iterate.com/capability-host/script-run-settled. - The runner accepts one script shape:
async (itx) => .... Endpoint-specific vars are baked into the source before it reaches the runner. /api/itx/runrecords requested/completed script events around a synchronous run; an enqueued requested event asks the context processor to run it later.- Individual itx capability calls do not create durable function-call-requested/completed events. The dotted path is captured by the path proxy and dispatched once through the itx supervisor.
- A provided capability may be a live object/function, a Worker RPC address, or a path-call target implementing
call({ path, args }). - A returned live handle, such as a Repo handle from
itx.repos.get({ path }), exposes its own Workers RPC methods after the original path call returns. itx.__describe()is the capability discovery surface. Providers attach instructions and optional types to each capability entry.- Dynamic MCP and OpenAPI tools should be exposed as itx capabilities whose exact external tool names or operation IDs remain path segments; use bracket syntax when a segment contains dots.
- Project default capabilities include
fetch,streams,secrets,integrations,repos,agents,workspace,worker, andaias defined byPLATFORM_PROJECT_CAPABILITIES. - Agent hosts add channel and agent-local capabilities such as
itx.chat,itx.debug,itx.agents, and an agent-privateitx.workspace; connected services remain on the project-owneditx.integrationscollection.
Target itx Blocks#
await itx.__describe();describe() is the runtime truth for a handle: it returns the context ref,
access shape, and the capabilities visible through the context chain.
await itx.integrations.slack.get().chat.postMessage({ channel: "C123", text: "hello" });Slack is a built-in integration family. get() resolves the first connected
workspace and its wrapped WebClient receives the remaining Slack Web API path.
const repo = await itx.repos.get({ path: "/repos/project" });
const info = await repo.getInfo();Repos are a project default capability. ReposCapability.call replays path
calls onto its WorkerEntrypoint methods; repo handles expose live Workers RPC
methods such as getInfo, commitFiles, readFiles, and readLog.
await itx.workspace.writeFile("/repos/config/worker.ts", source);
await itx.workspace.git.commit({ message, scope: "/repos/config" });Workspace is an explicit capability selected by the host. Agent contexts
provide their own isolated workspace — a private working copy of the
project's path namespace, with every project repo mounted at its own
/repos/** path and private files under the workspace's own directory.
const messages = await itx.integrations.gmail.get().request({
path: "/users/me/messages",
query: { maxResults: 5 },
});Gmail is a project integration backed by the first connected Google account
(or an explicit slug passed to get). It reads fresh OAuth access through the
secrets domain and proxies Gmail REST requests.
const response = await fetch("https://api.example.com/data");
const samePipe = await itx.fetch("https://api.example.com/data");Bare fetch() inside platform-loaded itx isolates and itx.fetch(...) both
flow through the project egress capability. A context can shadow fetch with
itx.provideCapability({ name: "fetch", ... }); secret placeholders are only
substituted in the default egress pipe.
const stream = itx.streams.get("/agents/demo");
await stream.append({ type: "events.example.com/note", payload: {} });
const events = await stream.getEvents();Streams are a project default capability. Narrowed project handles operate in the project namespace; absolute refs remain access-checked.
await itx.provideCapability({
name: "runSwiftOnMyMac",
instructions: "Compile and run Swift source on my laptop.",
capability: async (source) => runSwift(source),
});Live capabilities are session-bound and callable by every holder of the same context while the provider remains connected.
Example Dialogue#
Dev: "When a script runs
itx.linear.createIssue(...), is that a tool execution?" Domain expert: "It is an itx capability call. The dotted path is captured locally and dispatched once through the context supervisor."
Dev: "Is
itx.streams.get(path).append(...)a special stream API?" Domain expert: "No.streamsis a default project capability, and the returned stream handle is a live Workers RPC value."
Dev: "Does
itx.repos.get({ path }).getInfo()make two itx capability calls?" Domain expert: "Therepos.getpath call returns a repo handle;getInfois a Workers RPC method on that returned handle."
Dev: "How does a script learn what is available?" Domain expert: "Call
itx.__describe(). Providers attach instructions and optional types to each capability."
Dev: "Should
docs.searchfrom an MCP server becomeitx.docs.search(...)?" Domain expert: "No. External tool names and OpenAPI operation IDs are exact path segments, so use bracket syntax such asitx.mcp.cloudflareDocs["docs.search"](...)when needed."
Dev: "What script shape should MCP
exec_typescriptsend?" Domain expert: "Use one async arrow function:async (itx) => { ... }. The/api/itx/runendpoint accepts{ itx, vars }at its API boundary and wraps it into that runner shape."
Dev: "Is an outbound MCP capability the same thing as OS's MCP server connection?" Domain expert: "No. Outbound MCP From Our Client Capability is OS as an MCP client. Inbound MCP is an external client connected to OS's project-scoped MCP server."
Dev: "What are the two MCP directions in OS?" Domain expert: "Inbound MCP is OS acting as the MCP server via the stateless fetch-based OS MCP Handler. Outbound MCP is OS acting as an MCP client via
OutboundMcpFromOurClientCapability, which can be exposed as an itx capability."
Dev: "Can someone open an OS project page without signing in?" Domain expert: "No. The OS App is authenticated, and every Project is managed through the user's active Organization."
Dev: "Can a Personal Account own a Project?" Domain expert: "No. OS only lets an Organization own Projects."
Dev: "Can a project page be addressed without the organization slug?" Domain expert: "Yes. A Project Route is
/projects/:projectSlug; OS URLs have no organization segment — organization membership and selection live in the auth worker."
Dev: "What should OS show after sign-in if auth worker has no Active Organization?" Domain expert: "Redirect through the auth worker's organization selection or creation flow before rendering the OS App."
Dev: "Does the MCP server require an auth-worker JWT?" Domain expert: "No. The MCP server requires a valid OS admin token or auth-worker OAuth Access Token. JWT is a token format detail; OS should model the caller as a Principal."
Dev: "Should a request for a Project-owned hostname hit the OS App auth middleware before project routing?" Domain expert: "No. The OS Worker first classifies the Ingress Hostname. If it is a Project-Owned Hostname, the request becomes Project Ingress before OS App auth runs."
Dev: "Is the global hostname lookup a special project-hostname table?" Domain expert: "No. Model it as an Ingress Route Table. Matching an HTTP request yields a Fetch Destination; one such destination is the Project Durable Object."
Dev: "Do fallback routes live as rows in D1?" Domain expert: "No. They are Fallback Ingress Rules supplied by the caller, so a reader can understand the default behavior from the Worker or Project Durable Object source."
Dev: "Should the TanStack Start worker itself be the public entrypoint?" Domain expert: "Not necessarily. Prefer a skinny OS Ingress Worker as the public entrypoint, with the OS App Worker reachable only through a service binding."
Dev: "Should an ingress rule store a nested
{ callable: ... }destination?" Domain expert: "No. Store the route target directly as a top-level Fetch Callable on the rule."
Dev: "Should v1 route matching support path and header predicates?" Domain expert: "No. Use Exact Host Ingress Rules first so the lookup stays a direct indexed SQL query."
Dev: "Should the Project Durable Object be deployed in a separate worker script immediately?" Domain expert: "Not yet. Keep it exported from the main OS Worker while Project ingress depends on Loopback Fetch Callables with dynamic props."
Dev: "Does
/mcpon a Project-owned hostname route to the Project MCP server?" Domain expert: "No. MCP is served by the OS app's/api/mcproute; the canonical MCP resource URL is the OAuth identity, not a per-project hostname. OAuth sessions expose token-granted projects, admin-token sessions expose all projects, and project-scoped tools select one project per invocation."
Dev: "Does the Project Durable Object need to understand MCP protocol paths?" Domain expert: "No. The OS MCP Handler owns protocol paths, OAuth metadata, and unsupported-path responses."
Dev: "Should Project Durable Object expose
authorizeMcpServerConnection(...)?" Domain expert: "No. MCP is one Project Route Destination among many. Future authorization should be generic Project Route Authorization, not a method per destination type."
Dev: "How should MCP check access in v1 after verifying auth-worker OAuth?" Domain expert: "Use the verified Principal. Auth-worker project claims authorize directly; the legacy D1 Project projection remains a fallback for organization-owned projects."
Dev: "What should a global ingress rule point at for project traffic?" Domain expert: "Point it at
ProjectIngressEntrypoint, the Project Ingress Entry Point, with the stable Project ID in props. That entry point resolves the Project Durable Object and delegates to its ingress RPC."
Dev: "Is Project Egress just another Project Ingress route?" Domain expert: "No. Project Ingress handles inbound public requests to Project-owned hostnames. Project Egress is future outbound policy work; see
tasks/project-egress-secrets-mvp.md."
Dev: "Can
ProjectIngressEntrypointprops identify a Project by slug?" Domain expert: "Not in v1. Slugs are mutable and belong to control-plane routing. Hot ingress uses the stable Project ID already resolved by the exact-host route lookup."
Dev: "Which public host should OS use when linking to a Project?" Domain expert: "Use the slug platform host for now. The stable ID platform host remains routable; custom/default host selection is future work."
Dev: "Should the Project Durable Object command be named
initializeProject?" Domain expert: "No. Use Create Project Command /createProject.initializeis infrastructure lifecycle language, not the Project domain command."
Dev: "What happens to slug-derived hosts if the Project Slug changes?" Domain expert: "The slug-derived routes should change with the slug. The stable ID host remains routable; alias lifecycle can be added later."
Dev: "If
fetchCallable.props.projectIdalready contains the Project ID, should the ingress route row also have aproject_idcolumn?" Domain expert: "Yes. Data model scope should be first-class. Keepproject_idqueryable for listing, indexing, repair jobs, and ownership checks."
Dev: "Should TanStack routes or itx entrypoints implement project lifecycle logic directly?" Domain expert: "No. It should proxy project lifecycle commands to the Project Control Surface on the Project Durable Object. The app worker owns HTTP/auth plumbing, not the project lifecycle model."
Dev: "Is the global exact-host D1 route table authoritative?" Domain expert: "No. It is a Project Projection. The Project Durable Object owns desired project ingress state, while D1 gives the Worker a simple indexed lookup."
Dev: "Is the
projectsD1 table the source of truth for Project lifecycle?" Domain expert: "No. It is a Project Listing Projection. The Project Durable Object owns lifecycle state and writes the app-level D1 row for listing and routing."
Dev: "Is the automatic Durable Object tracking table the same thing as the
projectstable?" Domain expert: "No. The Durable Object Catalog is shared infrastructure state for initialized Durable Objects. The Project Listing Projection is product query state."
Flagged Ambiguities#
- "function" can mean a JavaScript function, an itx capability function, or a control operation. Resolved: use Path Call for itx-routed calls and ordinary "function" for JavaScript.
- "script" and "execution" were conflated. Resolved: Script is code; Script Execution is one attempt to run it.
- "execute" and "call" were used interchangeably. Resolved: scripts execute; itx capabilities receive Path Calls.
- "tools" was used for both the whole context and provider functions. Resolved: the local object is an itx Handle; provider callables are itx Capabilities.
- "describe callable" added a second provider execution path. Resolved:
capability registration carries short Capability Instructions; richer
discovery is exposed as ordinary capability methods such as
listTools,listOperations, orlistProcedures. - "ExecutionContext" conflicts with Cloudflare's Worker
ExecutionContext. Resolved: use itx Handle for itx userland. - "session id" and "stream path" were conflated. Resolved: itx contexts are explicit handles; Event Stream Path identifies streams, not an execution session.
- "app" can mean the OS product or a managed project surface. Resolved: use OS App for this dashboard and Project for the managed app surface.
- "personal organization" is misleading because auth worker treats personal accounts separately from organizations. Resolved: use Personal Account for auth worker's non-organization user context.
- "MCP JWT" is too narrow for auth-worker OAuth. Resolved: use OAuth Access Token for OAuth MCP bearer tokens and Principal for OS's request-local authenticated actor.
- "project URL" was ambiguous between stable IDs and slugs. Resolved: use Project Route for the user-facing
/projects/:projectSlugURL. - "MCP" can mean OS as an MCP server or OS as a client of another MCP server. Resolved: use OS MCP Handler for external clients connected to OS, and Outbound MCP From Our Client Capability for OS connecting to external MCP servers as itx capabilities.
- "Project Run Code Session" added an unnecessary layer. Resolved: run scripts against a Project-Scoped itx Handle.
- "route" can mean a TanStack route, a Worker hostname match, or a Project-local destination. Resolved: use Ingress Hostname for the Worker-level host classifier, Project Route for the authenticated OS dashboard URL, and Project Route Destination for a Project Durable Object target.
- "authentication" can happen at the OS App layer or inside MCP. Resolved: the OS App authenticates dashboard/control-plane routes; MCP auth currently lives in the OS MCP Handler.
- "fetch callable" overlaps with generic JavaScript functions and Tool Provider callables. Resolved: use Fetch Destination for an ingress target that can receive an HTTP request.
- "context request" made itx look like a generic invocation broker. Resolved: use Path Call for path-addressed itx capability calls.
- "documentation" sounded like a generated API schema or external docs page. Resolved: use Capability Instructions for the string-form guidance registered with a capability.
- "Workspace" is usually avoided for Organization or Project. Resolved: Workspace Durable Object is a minimal agent-associated durable tool provider, not an event-sourced workspace domain object.
- "
itx.workspaces.get" made Workspace look like a repo-style collection lookup. Resolved: use singularitx.workspacefor the Workspace surface. - "root tool" could imply a special non-provider mechanism. Resolved: subagent
creation is the namespaced RPC Capability
itx.agents.get(path).create(). - "path" was doing two jobs: identifying the full itx call and identifying the function relative to the provider. Resolved: use Capability Path for the registered mount path and Function Path for the capability-relative call path.
- "argsSummary" made path calls look like a separate event family. Resolved:
path calls carry an
argsfield and live values stay live across Workers RPC. - "static callable" sounded like one fixed descriptor. Resolved: use Callable Builder for helpers that construct different Callable descriptors for one Capability.
- "Project DO worker" conflicted with loopback props. Resolved: use Project Ingress Entry Point as the same-worker loopback target for project ingress, while the Project Durable Object remains exported by the main OS Worker.
- "project UI state" and lifecycle status could make the frontend look authoritative. Resolved: Project Lifecycle Events are durable facts, and UI can reduce them without owning the lifecycle model.
- "project identity" in entrypoint props could mean slug or ID. Resolved: v1 ingress entrypoints accept Project ID only; Project Slug resolution happens in control-plane routes or route-registry writes.
- "canonical project host" could mean stable ID host, slug host, or future custom host. Resolved for current code: use Stable Project Ingress Host for the ID-derived host and Slug Project Ingress Host for the slug-derived host.
- "initialize project" conflates infrastructure lifecycle with domain creation. Resolved: use Create Project Command for the Project Durable Object domain command.
- "scope" could be hidden inside payload JSON. Resolved: OS persisted records should expose their Data Scope through queryable columns.
- "source of truth" for project ingress could mean the global D1 lookup table. Resolved: the Project Durable Object owns desired ingress state; D1 rows are Project Projections.
- "project table" could mean app-level listing state or mixin-owned Durable Object tracking. Resolved: use Project Listing Projection for the app D1 row and Durable Object Catalog for shared DO tracking tables.
- "MCP authorization" could become a one-off Project Durable Object method. Resolved: avoid MCP-specific Project DO auth methods; model future auth as generic Project Route Authorization.
- "project access" and "route authorization" are different depths of policy. Resolved: v1 can use a generic Project Access Check; richer destination-specific policy belongs to future Project Route Authorization.
- "egress proxy", "egress gateway", and Project Ingress were used around outbound traffic. Resolved for current code: use Project Egress only as a pointer to future outbound policy work.
- "external egress proxy", "intercept egress traffic", and "mock internet proxy" were used for test-time outbound interception. Resolved: use Project Egress Fetch Shadow, or Project Egress Shadow as the short form.
externalEgressProxyUrlwas a persisted Project configuration field for test-time outbound interception. Resolved: remove it instead of preserving backwards compatibility; interception is a live itx-providedfetchcapability shadow."/__intercept-egress-fetch"and"/__iterate/intercept-project-egress"were both considered as connection paths. Resolved: there is no reserved HTTP connection path; the live shadow is provided over itx.- "Cloudflare Artifacts repo" introduced a second repo concept. Resolved: use Repo for the OS domain object and Cloudflare Artifacts for the backing service.
- "namespace" was used in OS code for the first component of stream and Durable Object identity. Resolved: object-form APIs should require a
projectIdfield, usingnullfor global scope, and encode Durable Object identity with a Durable Object Name. - Earlier Repo identifiers and relative repo paths made a Project-local stream child look like it had an identifier separate from its stream. Resolved: use Repo Path for the full Event Stream Path that identifies the Repo.
- "base repo" sounded like a Cloudflare Artifact name or special case. Resolved: the Iterate Config Base Repo is a global Repo Reference with
projectId: null. - Repo creation source used Artifact names and README bootstrap modes. Resolved: Repo Creation Source is only empty repo or fork from a Repo Reference; README writes are normal repo writes after creation.
- The Project Lifecycle Stream path was ambiguous between
/projectand/. Resolved: use root/; resource streams such as/repos/projectare child streams under the same Project ID. - "batch" implied one signed transaction covering many requests, so "Approval Group" was briefly used for requests presented together over per-request grant events. Resolved (reversed, ADR 0007): one signed transaction covering many requests is exactly the model — use Approval Batch; the requested event carries the request list and one decided event answers it.