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/:projectIdOrSlug handles, 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 via DurableObjectNameCodec ({projectId: string | null, path}), serves one capnweb surface at /api (context selection happens via projects.get(id) after authenticate()), and routes everything in src/worker.ts via the src/ingress.ts decision. See apps/os/src/README.md for 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/project are 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 projectId and 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/mcp Start route. The canonical MCP resource URL from APP_CONFIG_MCP__BASE_URL can point at a dedicated MCP hostname, and the OS app-host /api/mcp route 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-decided event 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 bare fetch(...) 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_CAPABILITY namespace 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 from durable-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_typescript starts a Script Execution and therefore requires a Script.
  • Browser REPL execution and Project MCP server exec_typescript share 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 executionId on events.iterate.com/capability-host/script-run-requested and events.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/run records 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, and ai as defined by PLATFORM_PROJECT_CAPABILITIES.
  • Agent hosts add channel and agent-local capabilities such as itx.chat, itx.debug, itx.agents, and an agent-private itx.workspace; connected services remain on the project-owned itx.integrations collection.

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. streams is 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: "The repos.get path call returns a repo handle; getInfo is 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.search from an MCP server become itx.docs.search(...)?" Domain expert: "No. External tool names and OpenAPI operation IDs are exact path segments, so use bracket syntax such as itx.mcp.cloudflareDocs["docs.search"](...) when needed."

Dev: "What script shape should MCP exec_typescript send?" Domain expert: "Use one async arrow function: async (itx) => { ... }. The /api/itx/run endpoint 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 /mcp on a Project-owned hostname route to the Project MCP server?" Domain expert: "No. MCP is served by the OS app's /api/mcp route; 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 ProjectIngressEntrypoint props 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. initialize is 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.projectId already contains the Project ID, should the ingress route row also have a project_id column?" Domain expert: "Yes. Data model scope should be first-class. Keep project_id queryable 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 projects D1 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 projects table?" 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, or listProcedures.
  • "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/:projectSlug URL.
  • "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 singular itx.workspace for 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 args field 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.
  • externalEgressProxyUrl was a persisted Project configuration field for test-time outbound interception. Resolved: remove it instead of preserving backwards compatibility; interception is a live itx-provided fetch capability 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 projectId field, using null for 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 /project and /. Resolved: use root /; resource streams such as /repos/project are 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.

Was this page helpful?