Skip to content

itx design notes + handwritten types.ts (design of record)#1428

Merged
jonastemplestein merged 1 commit into
mainfrom
medieval-fibre
Jun 10, 2026
Merged

itx design notes + handwritten types.ts (design of record)#1428
jonastemplestein merged 1 commit into
mainfrom
medieval-fibre

Conversation

@jonastemplestein

@jonastemplestein jonastemplestein commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What

Two design artifacts from the post-#1407 itx review sessions — docs/types only, no runtime changes.

apps/os/docs/itx-next.md — the working roadmap

The running list of what we want to fix or build in the itx layer, with positions, a decisions log, and open questions. Highlights:

  • CapTarget: a capability is a name + a target; the target is one discriminated union of three kinds — live (inbound: a connected provider's stub, the one non-serializable kind), rpc (outbound: an RPC target in some worker, with WorkerRef naming where that worker lives — binding / loopback / project-worker / durable-object / stored source), and url (a Cap'n Web server across the internet, headers pass through egress secret substitution). Inbound/outbound is derived, never spelled.
  • MCP/OpenAPI are not transports — they're client implementations, i.e. ordinary RPC targets. Litmus test: the first-party McpClient (loopback) and a user-space OpenApiClient (exported from your own project worker) must be the same shape.
  • One caps.define verb; kind: "facet" dies (statefulness is source.exportType).
  • Platform bindings as caps: thin policy wrappers (gateway selection, attribution) via loopback entrypoints — the ProjectEgress pattern applied to bindings.
  • A real global context + the ref-addressing model (refs are unauthenticated sturdy refs; resolution checks the principal; absolute forms are sugar over narrowing).
  • Codemode drop plan: a session = a forked child context; tool providers = caps; execution = two events (itx/execution-requested|completed), record-only first.
  • Streams convergence direction, sturdy-refs receipts (Cap'n Proto persistent.capnp), resolved-decisions log, open questions.

apps/os/src/itx/types.ts — the design of record

Handwritten, import-free. Narrative header (the three concepts + a thirty-second worked example), then Itx/ItxBuiltins, the KnownCaps declaration-merge point, CapTarget/WorkerRef, CapSource (with cacheKey, formerly codeId), ItxPrincipal hand-mirrored from ~/auth/principal.ts (no invented access model), StreamRef addressing forms, and CapMeta as arbitrary metadata with the instructions convention. The implementation conforms to this file in follow-up PRs; it also doubles as the REPL completion source.

Why

We want the design pinned down and reviewable before the kernel (protocol.ts/registry.ts) migrates to it. Next slices build on this: CapTarget in the registry (itx.ai via a binding ref as the proof), then the MCP/OpenAPI litmus pair, then the codemode drop.

🤖 Generated with Claude Code


Note

Low Risk
Documentation and type sketches only; no production code paths, auth, or data handling change in this PR.

Overview
Adds documentation-only design artifacts for the itx layer—no runtime or kernel changes.

apps/os/docs/itx-next.md is a working roadmap: CapTarget as live | rpc | url with WorkerRef (replacing today’s live | worker | facet); a single caps.define verb; MCP/OpenAPI as ordinary RPC clients, not protocol kinds; platform bindings as thin policy caps; a real global context and namespace-based stream addressing; a codemode → fork + caps + execution events migration plan; and a resolved/open-questions log.

apps/os/src/itx/types.ts is the import-free design of record: narrative plus types for Itx, CapTarget/WorkerRef/CapSource (cacheKey vs codeId), ItxPrincipal mirrored from auth, StreamRef, KnownCaps, and related wire types—intended for future implementation conformance, REPL completion, and agent-facing docs.

Reviewed by Cursor Bugbot for commit ee52a30. Bugbot is set up for automated code reviews on this repo. Configure here.

Environment Config Lease

No active environment config lease.

OS

Status: released
Commit: ee52a30
Preview: https://os.iterate-preview-2.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-10T12:06:49.270Z

Two artifacts from the post-#1407 itx design review:

- docs/itx-next.md: the working roadmap. CapTarget (live | rpc | url,
  with WorkerRef naming where an rpc target's worker lives), one
  caps.define verb, platform bindings as thin policy-wrapped caps, a
  real global context and the ref-addressing model, the codemode drop
  plan (two itx/execution-* events), streams convergence direction,
  decisions log and open questions.

- src/itx/types.ts: handwritten, import-free design-of-record surface.
  Narrative header (the three concepts + worked example), Itx/ItxBuiltins,
  KnownCaps merge point, CapTarget/WorkerRef, CapSource with cacheKey,
  ItxPrincipal mirrored by hand from the auth system, StreamRef
  addressing forms, CapMeta as arbitrary metadata with the instructions
  convention. Doubles as the REPL completion source.

Docs/types only — no runtime changes. The kernel implementation
(protocol.ts/registry.ts) migrates to this surface in follow-up PRs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jonastemplestein jonastemplestein merged commit 1d4dd92 into main Jun 10, 2026
9 checks passed
@jonastemplestein jonastemplestein deleted the medieval-fibre branch June 10, 2026 12:05
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
…1436)

Supersedes #1433, which GitHub auto-closed when its base branch
(`medieval-fibre`, merged as #1428) was deleted. Same commit, now based
on main.

## What

First implementation slice of the CapTarget design from #1428 (design of
record: `src/itx/types.ts`).

**A capability is now a name plus a typed target.** `caps.define`
accepts:

```ts
// raw platform binding — members replay applies the path onto env.AI
await itx.caps.define({
  name: "ai",
  target: { type: "rpc", worker: { type: "binding", binding: "AI" } },
});
await itx.ai.models();

// the same binding through the thin policy wrapper (itx-next §2 pattern)
await itx.caps.define({
  invoke: "path-call",
  name: "aiWrapped",
  target: { type: "rpc", worker: { type: "loopback" }, entrypoint: "BindingCapability", props: { binding: "AI" } },
});
```

- `registry.borrowTarget()` is the two-case switch the design promised:
live table, or resolve the stored target.
- Implemented worker refs: `binding`, `loopback`, `source` (the old
worker/facet paths, unchanged underneath). `url` / `durable-object` /
`project-worker` fail with informative not-implemented errors **at
define time**.
- `BindingCapability`: new loopback entrypoint, the thin policy wrapper
for bindings — gateway/quota policy slots in there later.
- `kind: "facet"` is gone from the API (legacy input still accepted):
statefulness is `source.exportType: "worker-entrypoint" |
"durable-object"`. `cacheKey` replaces `codeId` (deprecated alias kept).
- `CapMeta` is open metadata with the `instructions` convention, lifted
into `describe()` output.

## Security

`binding` and `loopback` refs reach **platform** resources (an open list
would let any project handle reach the deployment D1, or mint itx
handles on arbitrary projects via ItxEntrypoint props). They are gated
on hardcoded allowlists — `DIALABLE_BINDINGS = {AI}`,
`DIALABLE_LOOPBACKS = {BindingCapability}` — checked at define time
(fail fast) and again at dial time (authoritative). `BindingCapability`
re-checks the binding allowlist itself since its props are
definer-controlled. Config-driven lists are a follow-up.

## Compatibility

- `caps.define({ source, kind: "worker" | "facet" })` still works —
normalizes to an rpc/source target.
- Stored rows from before this PR (kind worker/facet + source_json)
normalize on read; new rows also write `source_json` for source targets
so a rollback can still read them. New `target_json` column added via
guarded ALTER.
- `describe()` now reports `kind: "rpc"` for stored-source caps (e2e
assertion updated).

## Testing

- `pnpm typecheck` / `lint` / `format` / `test` (190 unit tests) all
green.
- **Full `pnpm e2e:itx` suite ran green against a live deployment** (19
tests, 5 files, via the dev_jonas tunnel serving this branch):
`itx.ai.models()` through the real AI binding raw + wrapped, allowlist
refusals, and all pre-existing egress/facet/fork/HTTP tests — no
regressions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> Introduces platform binding and loopback dialing gated only on small
hardcoded allowlists; misconfiguration or future allowlist expansion
could expose env bindings like D1 or arbitrary loopback exports to
project handles.
> 
> **Overview**
> **Capabilities are now a name plus a typed `SerializableCapTarget`**,
not legacy `source` + `kind: worker | facet`. `caps.define` accepts
`target` (e.g. `rpc` with `binding`, `loopback`, or `source` worker
refs); old `source`/`kind` input still normalizes to `rpc`/`source`.
> 
> **Registry dispatch** is refactored to the two-case model: live
in-memory connections, or `resolveTarget()` at invoke time for stored
targets. SQLite gains `target_json` (with legacy row normalization via
`targetOf()`); `describe()` reports `kind: "rpc"` and lifts
`meta.instructions`.
> 
> **Platform binding exposure** adds `BindingCapability` (loopback
path-call wrapper), host `binding` resolvers on Project/Context DOs, and
**allowlists** `DIALABLE_BINDINGS` / `DIALABLE_LOOPBACKS` enforced at
define and dial time.
> 
> **Protocol updates**: `CapKind` becomes `live | rpc | url`; `cacheKey`
replaces `codeId`; `exportType` replaces facet kind; `url` /
`project-worker` / `durable-object` refs fail at define time until
implemented.
> 
> **E2E** covers raw `AI` binding caps, wrapped `BindingCapability`, and
allowlist rejections.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
13ab9e5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- CLOUDFLARE_PREVIEW -->
## Environment Config Lease
<!-- CLOUDFLARE_PREVIEW_STATE -->
<!--
{
  "apps": {
    "os": {
      "appDisplayName": "OS",
      "appSlug": "os",
      "status": "deployed",
      "updatedAt": "2026-06-10T12:11:14.008Z",
      "headSha": "13ab9e5ccc39a1348d29b74fd55086747b727bd6",
      "message": null,
      "publicUrl": "https://os.iterate-preview-2.com",
"runUrl": "https://github.com/iterate/iterate/actions/runs/27275038072",
      "shortSha": "13ab9e5"
    }
  },
  "environmentConfigLease": {
    "dopplerConfig": "preview_2",
    "leasedUntil": 1781096892787,
    "leaseId": "f42f975c-7672-4369-bcb7-2db7a29b7c06",
    "slug": "preview-2",
    "type": "environment-config-lease"
  }
}
-->
<!-- /CLOUDFLARE_PREVIEW_STATE -->
Lease: `preview-2`
Doppler config: `preview_2`
Type: `environment-config-lease`
Leased until: 2026-06-10T13:08:12.787Z

### OS
Status: deployed
Commit: `13ab9e5`
Preview: https://os.iterate-preview-2.com
[Workflow
run](https://github.com/iterate/iterate/actions/runs/27275038072)
Updated: 2026-06-10T12:11:14.008Z
<!-- /CLOUDFLARE_PREVIEW -->

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant