iterate 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +164 -82
- package/dist/{next/api.d.ts → api.d.ts} +197 -33
- package/dist/{next/app-server.d.ts → app-server.d.ts} +7 -0
- package/dist/{next/app-server.mjs → app-server.mjs} +17 -15
- package/dist/app-server.mjs.map +1 -0
- package/dist/{next/app-session.mjs → app-session.mjs} +12 -15
- package/dist/app-session.mjs.map +1 -0
- package/dist/{next/app.mjs → app.mjs} +53 -14
- package/dist/app.mjs.map +1 -0
- package/dist/{next/client → client}/live-state.d.ts +11 -11
- package/dist/client/oauth.d.ts +17 -0
- package/dist/{next/client → client}/react.d.ts +10 -42
- package/dist/{next/client → client}/socket.d.ts +1 -0
- package/dist/client.mjs +156 -4
- package/dist/client.mjs.map +1 -0
- package/dist/{next/expression.d.ts → expression.d.ts} +11 -69
- package/dist/{next/expression.mjs → expression.mjs} +11 -109
- package/dist/expression.mjs.map +1 -0
- package/dist/lib-BWr-5mFO.mjs +36 -0
- package/dist/lib-BWr-5mFO.mjs.map +1 -0
- package/dist/{next/lib.d.ts → lib.d.ts} +16 -2
- package/dist/{next/lib.mjs → lib.mjs} +32 -3
- package/dist/lib.mjs.map +1 -0
- package/dist/node.d.ts +15 -3
- package/dist/node.mjs +36 -174
- package/dist/node.mjs.map +1 -1
- package/dist/{next/oauth-scopes.mjs → oauth-scopes.mjs} +1 -1
- package/dist/oauth-scopes.mjs.map +1 -0
- package/dist/{next/oauth.mjs → oauth.mjs} +14 -2
- package/dist/oauth.mjs.map +1 -0
- package/dist/principal.d.ts +8 -0
- package/dist/principal.mjs +8 -0
- package/dist/principal.mjs.map +1 -0
- package/dist/project-ingress.d.ts +58 -0
- package/dist/project-ingress.mjs +104 -0
- package/dist/project-ingress.mjs.map +1 -0
- package/dist/{next/react.mjs → react.mjs} +12 -12
- package/dist/react.mjs.map +1 -0
- package/dist/sdk/auth.d.ts +25 -0
- package/dist/sdk/index.d.ts +155 -0
- package/dist/sdk/record-pipelined-steps.d.ts +19 -0
- package/dist/sdk.mjs +245 -2
- package/dist/sdk.mjs.map +1 -0
- package/dist/{next/stream → stream}/processor.d.ts +28 -23
- package/dist/{next/stream → stream}/processor.mjs +48 -25
- package/dist/stream/processor.mjs.map +1 -0
- package/dist/{next/stream → stream}/run.d.ts +9 -6
- package/dist/{next/stream → stream}/run.mjs +13 -8
- package/dist/stream/run.mjs.map +1 -0
- package/dist/stream/test-support.d.ts +45 -0
- package/dist/stream/test-support.mjs +196 -0
- package/dist/stream/test-support.mjs.map +1 -0
- package/package.json +65 -219
- package/THIRD_PARTY_NOTICES.md +0 -55
- package/bin/iterate.js +0 -94
- package/dist/api-url-B6404M82.mjs +0 -17
- package/dist/api-url-B6404M82.mjs.map +0 -1
- package/dist/app-ref-BipL0feU.mjs +0 -35
- package/dist/app-ref-BipL0feU.mjs.map +0 -1
- package/dist/app-ref-C1CrgXqX.mjs +0 -7
- package/dist/app-ref-C1CrgXqX.mjs.map +0 -1
- package/dist/app-ref-DYai_om1.mjs +0 -7
- package/dist/app-ref-DYai_om1.mjs.map +0 -1
- package/dist/cli-D0c-pDL_.mjs +0 -1010
- package/dist/cli-D0c-pDL_.mjs.map +0 -1
- package/dist/client.d.ts +0 -3
- package/dist/cloudflare-BTm90gQ4.mjs +0 -951
- package/dist/cloudflare-BTm90gQ4.mjs.map +0 -1
- package/dist/contract-s4FW4eES.mjs +0 -309
- package/dist/contract-s4FW4eES.mjs.map +0 -1
- package/dist/document-review/index.d.ts +0 -5
- package/dist/document-review/types.d.ts +0 -107
- package/dist/document-review.mjs +0 -7015
- package/dist/document-review.mjs.map +0 -1
- package/dist/durable-object-processor-durability-CNsTjAJS.mjs +0 -205
- package/dist/durable-object-processor-durability-CNsTjAJS.mjs.map +0 -1
- package/dist/idempotency-DleloJNt.mjs +0 -28
- package/dist/idempotency-DleloJNt.mjs.map +0 -1
- package/dist/index.d.mts +0 -5
- package/dist/index.mjs +0 -8
- package/dist/index.mjs.map +0 -1
- package/dist/itx/api-url.d.ts +0 -6
- package/dist/itx/itx-node-client.d.ts +0 -65
- package/dist/itx/itx-session.d.ts +0 -215
- package/dist/itx/owned-rpc-session.d.ts +0 -14
- package/dist/itx/query-client.d.ts +0 -10
- package/dist/itx-api.generated.d.ts +0 -6195
- package/dist/itx-session-sjud8GiT.mjs +0 -534
- package/dist/itx-session-sjud8GiT.mjs.map +0 -1
- package/dist/live-state-BJNqOwFw.mjs +0 -299
- package/dist/live-state-BJNqOwFw.mjs.map +0 -1
- package/dist/next/app-server.mjs.map +0 -1
- package/dist/next/app-session.mjs.map +0 -1
- package/dist/next/app.mjs.map +0 -1
- package/dist/next/client/oauth.d.ts +0 -12
- package/dist/next/client.mjs +0 -156
- package/dist/next/client.mjs.map +0 -1
- package/dist/next/expression.mjs.map +0 -1
- package/dist/next/lib.mjs.map +0 -1
- package/dist/next/oauth-scopes.mjs.map +0 -1
- package/dist/next/oauth.mjs.map +0 -1
- package/dist/next/principal.d.ts +0 -64
- package/dist/next/principal.mjs +0 -98
- package/dist/next/principal.mjs.map +0 -1
- package/dist/next/project-ingress.d.ts +0 -37
- package/dist/next/project-ingress.mjs +0 -75
- package/dist/next/project-ingress.mjs.map +0 -1
- package/dist/next/react.mjs.map +0 -1
- package/dist/next/sdk/auth.d.ts +0 -5
- package/dist/next/sdk/index.d.ts +0 -112
- package/dist/next/sdk.mjs +0 -139
- package/dist/next/sdk.mjs.map +0 -1
- package/dist/next/stream/processor.mjs.map +0 -1
- package/dist/next/stream/run.mjs.map +0 -1
- package/dist/next-node.d.ts +0 -15
- package/dist/next-node.mjs +0 -51
- package/dist/next-node.mjs.map +0 -1
- package/dist/processor-host-capabilities-BMFH3KTM.mjs +0 -56
- package/dist/processor-host-capabilities-BMFH3KTM.mjs.map +0 -1
- package/dist/processors/cloudflare.d.ts +0 -3
- package/dist/processors/durable-object-processor-durability.d.ts +0 -79
- package/dist/processors/event-consumption-metrics.d.ts +0 -82
- package/dist/processors/idempotency.d.ts +0 -13
- package/dist/processors/index.d.ts +0 -12
- package/dist/processors/processor-contracts.d.ts +0 -342
- package/dist/processors/processor-facet.d.ts +0 -186
- package/dist/processors/processor-host-capabilities.d.ts +0 -60
- package/dist/processors/prompt-sections.d.ts +0 -17
- package/dist/processors/rpc-types.d.ts +0 -515
- package/dist/processors/schemas.d.ts +0 -102
- package/dist/processors/stream-handle.d.ts +0 -45
- package/dist/processors/stream-processor-keepalive.d.ts +0 -95
- package/dist/processors/stream-processor-registry.d.ts +0 -233
- package/dist/processors/stream-processor-runner.d.ts +0 -289
- package/dist/processors/stream-processor.d.ts +0 -339
- package/dist/processors/stream-runtime-metrics.d.ts +0 -107
- package/dist/processors/testing.d.ts +0 -302
- package/dist/processors-BoNyeBfQ.mjs +0 -10
- package/dist/processors-BoNyeBfQ.mjs.map +0 -1
- package/dist/processors-cloudflare.mjs +0 -3
- package/dist/processors-testing.mjs +0 -435
- package/dist/processors-testing.mjs.map +0 -1
- package/dist/processors.mjs +0 -52
- package/dist/processors.mjs.map +0 -1
- package/dist/protocol-DnK_f2m6.mjs +0 -251
- package/dist/protocol-DnK_f2m6.mjs.map +0 -1
- package/dist/sdk/capnweb/index.d.ts +0 -2
- package/dist/sdk/capnweb/live-state/compact.d.ts +0 -5
- package/dist/sdk/capnweb/live-state/diff.d.ts +0 -41
- package/dist/sdk/capnweb/live-state/engine.d.ts +0 -44
- package/dist/sdk/capnweb/live-state/index.d.ts +0 -41
- package/dist/sdk/capnweb/live-state/protocol.d.ts +0 -87
- package/dist/sdk/capnweb/live-state/retain.d.ts +0 -23
- package/dist/sdk/capnweb/live-state/store.d.ts +0 -20
- package/dist/sdk/capnweb/live-state/types.d.ts +0 -11
- package/dist/sdk/capnweb/react.d.ts +0 -45
- package/dist/sdk/capnweb/react.mjs +0 -316
- package/dist/sdk/capnweb/react.mjs.map +0 -1
- package/dist/sdk/capnweb.mjs +0 -4
- package/dist/sdk/itx/react.d.ts +0 -191
- package/dist/sdk/itx/react.mjs +0 -383
- package/dist/sdk/itx/react.mjs.map +0 -1
- package/dist/sdk-DMB-IM11.mjs +0 -933
- package/dist/sdk-DMB-IM11.mjs.map +0 -1
- package/dist/sdk.d.ts +0 -339
- package/dist/serve-itx.d.ts +0 -46
- package/dist/starter-apps/flake-dashboard/app-ref.d.ts +0 -31
- package/dist/starter-apps/flake-dashboard/configured-worker.mjs +0 -1055
- package/dist/starter-apps/flake-dashboard/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/flake-dashboard/contract.d.ts +0 -4839
- package/dist/starter-apps/flake-dashboard/contract.mjs +0 -2
- package/dist/starter-apps/flake-dashboard/index.d.ts +0 -17
- package/dist/starter-apps/flake-dashboard/index.mjs +0 -56
- package/dist/starter-apps/flake-dashboard/index.mjs.map +0 -1
- package/dist/starter-apps/flake-dashboard/worker.d.ts +0 -4607
- package/dist/starter-apps/github-ai-linter/ai-linter.d.ts +0 -8914
- package/dist/starter-apps/github-ai-linter/configured-worker.mjs +0 -17987
- package/dist/starter-apps/github-ai-linter/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/github-ai-linter/contract.d.ts +0 -9193
- package/dist/starter-apps/github-ai-linter/index.d.ts +0 -10
- package/dist/starter-apps/github-ai-linter/index.mjs +0 -36
- package/dist/starter-apps/github-ai-linter/index.mjs.map +0 -1
- package/dist/starter-apps/github-ai-linter/prompt.d.ts +0 -13
- package/dist/starter-apps/github-ai-linter/review-bot.d.ts +0 -808
- package/dist/starter-apps/github-ai-linter/rules.d.ts +0 -34
- package/dist/starter-apps/github-ai-linter/worker-ref.d.ts +0 -19
- package/dist/starter-apps/github-ai-linter/worker.d.ts +0 -19
- package/dist/starter-apps/github-ai-linter/worker.mjs +0 -947
- package/dist/starter-apps/github-ai-linter/worker.mjs.map +0 -1
- package/dist/starter-apps/guestbook/app-ref.d.ts +0 -27
- package/dist/starter-apps/guestbook/client.d.ts +0 -7
- package/dist/starter-apps/guestbook/client.mjs +0 -59
- package/dist/starter-apps/guestbook/configured-worker.mjs +0 -205
- package/dist/starter-apps/guestbook/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/guestbook/index.d.ts +0 -9
- package/dist/starter-apps/guestbook/index.mjs +0 -31
- package/dist/starter-apps/guestbook/index.mjs.map +0 -1
- package/dist/starter-apps/guestbook/processor.d.ts +0 -2267
- package/dist/starter-apps/guestbook/worker.d.ts +0 -26
- package/dist/starter-apps/guestbook/worker.mjs +0 -191
- package/dist/starter-apps/guestbook/worker.mjs.map +0 -1
- package/dist/starter-apps/media/configured-worker.mjs +0 -577
- package/dist/starter-apps/media/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/media/index.mjs +0 -36
- package/dist/starter-apps/media/index.mjs.map +0 -1
- package/dist/starter-apps/media/ref.mjs +0 -20
- package/dist/starter-apps/media/ref.mjs.map +0 -1
- package/dist/starter-apps/media/worker.mjs +0 -579
- package/dist/starter-apps/media/worker.mjs.map +0 -1
- package/dist/starter-apps/notes/configured-worker.mjs +0 -6134
- package/dist/starter-apps/notes/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/notes/index.mjs +0 -23
- package/dist/starter-apps/notes/index.mjs.map +0 -1
- package/dist/starter-apps/notes/ref.mjs +0 -21
- package/dist/starter-apps/notes/ref.mjs.map +0 -1
- package/dist/starter-apps/notes/worker.mjs +0 -427
- package/dist/starter-apps/notes/worker.mjs.map +0 -1
- package/dist/starter-apps/todo/client.mjs +0 -59
- package/dist/starter-apps/todo/configured-worker.mjs +0 -2864
- package/dist/starter-apps/todo/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/todo/index.d.ts +0 -8
- package/dist/starter-apps/todo/index.mjs +0 -29
- package/dist/starter-apps/todo/index.mjs.map +0 -1
- package/dist/stream-processor-keepalive-DAQTP6m3.mjs +0 -2082
- package/dist/stream-processor-keepalive-DAQTP6m3.mjs.map +0 -1
- package/dist/usingCtx-mZx5nsAW.mjs +0 -11800
- package/dist/usingCtx-mZx5nsAW.mjs.map +0 -1
- package/dist/worker-ref-DZxPDmb_.mjs +0 -390
- package/dist/worker-ref-DZxPDmb_.mjs.map +0 -1
- package/dist/worker.d.mts +0 -33
- package/dist/worker.mjs +0 -18
- package/dist/worker.mjs.map +0 -1
- package/menubar/Iterate.entitlements +0 -12
- package/menubar/Iterate.swift +0 -914
- package/menubar/IterateIcon.swift +0 -145
- package/menubar/README.md +0 -28
- package/menubar/build-menubar-app.sh +0 -59
- /package/dist/{next/api.mjs → api.mjs} +0 -0
- /package/dist/{next/app-session.d.ts → app-session.d.ts} +0 -0
- /package/dist/{next/app.d.ts → app.d.ts} +0 -0
- /package/dist/{next/oauth-scopes.d.ts → oauth-scopes.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,107 +1,189 @@
|
|
|
1
1
|
# iterate
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
`
|
|
22
|
-
`
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
3
|
+
The SDK for Iterate (`apps/os`): context APIs, stream processors, reactive clients, React
|
|
4
|
+
bindings, and OAuth app sessions, under `iterate/*`. The package exports source in this
|
|
5
|
+
workspace and compiled JavaScript with declarations when packed. The `iterate` command is
|
|
6
|
+
[`@iterate-com/cli`](../cli/README.md).
|
|
7
|
+
|
|
8
|
+
## The SDK/platform line
|
|
9
|
+
|
|
10
|
+
The SDK holds what user code runs or speaks, and the platform is its first user: apps/os builds
|
|
11
|
+
its own entities on `iterate/sdk`, and the first-party apps' code uses only `iterate/*`. Each
|
|
12
|
+
subpath in `package.json`'s `exports` is one public module; nothing else is importable.
|
|
13
|
+
|
|
14
|
+
- A module belongs here when user code runs it or speaks it: a loaded worker, a facet, a
|
|
15
|
+
processor, a browser or Node client, or the wire contract between them and the platform. It
|
|
16
|
+
belongs in apps/os when only the platform's Worker runs it, and in packages/shared when more
|
|
17
|
+
than one app needs it and user code never does.
|
|
18
|
+
- Outside apps/os, no package and no app imports apps/os. `import-js/no-restricted-paths` in
|
|
19
|
+
`.oxlintrc.json` resolves each import under `packages/**` and `apps/**` to a file, so type
|
|
20
|
+
imports, re-exports, dynamic `import()` and an app added later are covered, and
|
|
21
|
+
`lint/oxlintrc-platform-line.test.ts` pins it. Tests may import apps/os's two harnesses,
|
|
22
|
+
`apps/os/e2e/support/` and `apps/os/__workers-tests__/support.ts`, which drive a real platform.
|
|
23
|
+
- The one known exception: the git codec (`@iterate-com/shared/git-wire`) and the GitHub template
|
|
24
|
+
reader live in packages/shared, though only the platform's Worker runs them. packages/shared is
|
|
25
|
+
private, so they do not cross the line.
|
|
26
|
+
- No private core package behind a thin `iterate`: apps/os would then import modules user code
|
|
27
|
+
cannot, and the SDK's types would have to be bundled or published anyway.
|
|
28
|
+
|
|
29
|
+
Follow-ups: move the git codec and the template reader into `apps/os/src/repo/`, and type the test
|
|
30
|
+
harnesses against `iterate/api`. The decision's reasons, and how workerd, the Agents SDK, Convex,
|
|
31
|
+
Supabase, tRPC, Hono and Wrangler draw the same line:
|
|
32
|
+
[the decision record](https://github.com/iterate/iterate/blob/d52a4e8e0f791c96b683fe178b56570532123c05/docs/2026-09-24-sdk-platform-line.md)
|
|
33
|
+
(#3018).
|
|
34
|
+
|
|
35
|
+
## Reaching the context from loaded code
|
|
36
|
+
|
|
37
|
+
Code the platform loads for a project (a config worker, a facet, a worker behind a rewrite rule)
|
|
38
|
+
imports the SDK as `./processor.js` and reaches its context through `withItx`: one round trip,
|
|
39
|
+
after which the scope, every call made through it and every handle it awaited are released.
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
config's `defaultProject`, or the only project accessible to the session.
|
|
41
|
+
```js
|
|
42
|
+
import { ConfigWorker, withItx } from "./processor.js";
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
export default class extends ConfigWorker {
|
|
45
|
+
async fetch() {
|
|
46
|
+
// An SDK host (ConfigWorker, StreamProcessorDurableObject) has it as a method.
|
|
47
|
+
const { projectSlug } = await this.withItx((itx) => itx.whoami());
|
|
48
|
+
return new Response(`Homepage of ${projectSlug}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
45
51
|
|
|
46
|
-
|
|
52
|
+
// Anywhere else: withItx(this.env.ITX, (itx) => itx.kv.get("key"))
|
|
53
|
+
```
|
|
47
54
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
Never keep what `env.ITX.get()` hands out, and answer data, not handles, from `withItx`: a kept
|
|
56
|
+
scope, step or handle keeps the context, and any facet holding it, resident after the project goes
|
|
57
|
+
idle. An object that needs
|
|
58
|
+
reach takes a `WithItx` accessor (`(call) => withItx(this.env.ITX, call)`), never a scope; work
|
|
59
|
+
that outlives the call runs under a processor's `runInBackground` claim. Lint refuses a raw
|
|
60
|
+
`ITX.get()` in this repository (`iterate/no-raw-itx-get`).
|
|
52
61
|
|
|
53
|
-
|
|
54
|
-
you trust: its callers can run local code. The capability belongs to the live
|
|
55
|
-
connection and is released on exit. A disconnect or token expiry ends sharing
|
|
56
|
-
with an error; rerun the command to refresh authentication and reconnect.
|
|
62
|
+
## Testing a processor
|
|
57
63
|
|
|
58
|
-
|
|
64
|
+
`iterate/stream/test-support` (Node) is the harness the SDK's own engine tests use:
|
|
59
65
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
a single saved config, then built-in `prd`.
|
|
66
|
+
```ts
|
|
67
|
+
import { reduceProcessor } from "iterate/stream/test-support";
|
|
63
68
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
iterate --config next login
|
|
68
|
-
iterate config set --name local --os-base-url http://localhost:8787 --set-workspace
|
|
69
|
-
iterate config list
|
|
70
|
-
iterate config get
|
|
69
|
+
// apps/os/src/client/presence/processor.test.ts: durable ticks are reduced, ephemeral pokes are not
|
|
70
|
+
const state = reduceProcessor(new PresenceProcessor(), [{ type: "tick" }, { type: "poke" }]);
|
|
71
|
+
// state.ticks === 1
|
|
71
72
|
```
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
server clears that config's session. There is no separate `authBaseUrl` setting.
|
|
76
|
-
|
|
77
|
-
The old chat TUI and remotely discovered `iterate os ...` commands are removed.
|
|
78
|
-
The menu bar supports sign-in and computer sharing. Approval code is retained
|
|
79
|
-
but dormant until OS Next supports it. Use `iterate itx run` for scripts;
|
|
80
|
-
its `--project` selects the project and `--context` selects a path within it.
|
|
81
|
-
|
|
82
|
-
## Node REPL
|
|
83
|
-
|
|
84
|
-
`iterate repl` opens a local Node REPL with the authenticated session as `itx`
|
|
85
|
-
(try `await itx.projects.list()`) and the transport's `RpcTarget` constructor.
|
|
86
|
-
Pass `--project my-project --context /` to bind `itx` to a project context;
|
|
87
|
-
a configured `defaultProject` also selects a project. Top-level `await`, Node APIs and `.load` are available. The bindings remain available after `.clear`; `.exit` releases the context and connection. A lost connection
|
|
88
|
-
ends the REPL visibly; it never silently repeats your commands.
|
|
74
|
+
`memoryStream`, `memoryStorage` and `settle` drive a whole `ProcessorEngine` against an
|
|
75
|
+
in-memory log (`src/stream/processor.test.ts` shows how).
|
|
89
76
|
|
|
90
77
|
## Node connections
|
|
91
78
|
|
|
92
|
-
`iterate/
|
|
79
|
+
`iterate/node` exposes a connection owner for Iterate scripts and live
|
|
93
80
|
providers. It uses the same protocol and cleanup as the CLI:
|
|
94
81
|
|
|
95
82
|
```js
|
|
96
|
-
import {
|
|
83
|
+
import { connectIterate } from "iterate/node";
|
|
97
84
|
|
|
98
|
-
using connection = await
|
|
99
|
-
baseUrl: "https://os.
|
|
85
|
+
using connection = await connectIterate({
|
|
86
|
+
baseUrl: "https://os.iterate.com",
|
|
100
87
|
auth: { type: "bearer", token: process.env.ITERATE_BEARER_TOKEN },
|
|
101
88
|
});
|
|
102
89
|
using project = await connection.session.projects.get("my-project");
|
|
103
90
|
console.log(await project.run("async (itx) => await itx.whoami()"));
|
|
104
91
|
```
|
|
105
92
|
|
|
106
|
-
|
|
107
|
-
|
|
93
|
+
## Event types
|
|
94
|
+
|
|
95
|
+
A platform event type is `events.iterate.com/<namespace>/<event>`: one namespace segment and one
|
|
96
|
+
event segment, both lowercase kebab-case, and never a third segment.
|
|
97
|
+
|
|
98
|
+
Every type under `events.iterate.com/` follows these rules, test types included. A type without
|
|
99
|
+
that prefix belongs to whoever appends it and is opaque to the platform: tests use types like
|
|
100
|
+
`demo/ping` on purpose, and a project may use its own domain (`events.garple.com/sales/…`).
|
|
101
|
+
|
|
102
|
+
### Namespaces
|
|
103
|
+
|
|
104
|
+
- **`itx`** holds the context engine's own events: everything the core contract
|
|
105
|
+
(`apps/os/src/stream/core-processor.ts`) reduces, validates or refuses, plus the records the
|
|
106
|
+
Stream, the context Durable Object and the SDK processor host write themselves. Where the schema
|
|
107
|
+
and the reduce live decides it, not which contexts hold the event: fetch routes and the apex
|
|
108
|
+
ingress target are core state, so they are `itx` even though only a project root's copy is read.
|
|
109
|
+
A domain processor may consume an `itx` event (the agent consumes `itx/run-*`, the Project
|
|
110
|
+
processor `itx/ingress-configured`); it names the core's catalog in its `processorDeps` rather than
|
|
111
|
+
defining the event itself. The core's checkpoint slug is `core`: it is a storage key, not a type
|
|
112
|
+
prefix.
|
|
113
|
+
- **A domain namespace** is the singular name of the kind of context whose log the event belongs
|
|
114
|
+
to, which is the defining contract's slug when there is one: `account`, `organization`,
|
|
115
|
+
`project`, `repo`, `workspace`, `secret`, `agent`, `voice-agent`. A fact cross-posted to another
|
|
116
|
+
log keeps its own namespace: `repo/created` on `/` is still a repo fact.
|
|
117
|
+
- **An integration** uses its own name as its namespace, for example `chrome`.
|
|
118
|
+
- **`test`** holds types that only tests append. Production code never matches a `test/*` type. A
|
|
119
|
+
test contract may keep a slug of its own (`counter`), but its events go under `test/`. A test must
|
|
120
|
+
not borrow a production namespace for a type that does not exist.
|
|
121
|
+
|
|
122
|
+
### Event names
|
|
123
|
+
|
|
124
|
+
- **A fact is past tense**: `<object>-<verb-ed>`, or a bare `<verb-ed>` when the object is the
|
|
125
|
+
namespace's own subject (`itx/created` is the context, `agent/paused` is the agent). The object
|
|
126
|
+
comes first and is singular.
|
|
127
|
+
- **Spell words out.** Clipped words are not allowed (`spk`); a real word is (`mic`), and so is an
|
|
128
|
+
acronym the API already spells (`llm`, `rpc`, `itx`).
|
|
129
|
+
- **Asking and answering.** `<x>-requested` asks, and its offset identifies the ask. The answer
|
|
130
|
+
takes one of three shapes:
|
|
131
|
+
- `<x>-settled` is the one terminal fact when the asker reads a result. It names
|
|
132
|
+
`requestOffset` and carries the outcome: succeeded, failed or cancelled, a status, or an error.
|
|
133
|
+
Examples: `itx/run-*`, `agent/llm-request-*`, `project/hostname-add-*`.
|
|
134
|
+
- `<verb-ed>` or `<verb>-failed` is used when success is a fact that other logs wait on, like a
|
|
135
|
+
certificate: `create-requested` → `created` or `create-failed`, `delete-requested` → `deleted`,
|
|
136
|
+
`hostname-remove-requested` → `hostname-removed`. A failure that is retried rather than
|
|
137
|
+
reported gets no `-failed` fact.
|
|
138
|
+
- An answer that is also a fact of its own names the ask by id:
|
|
139
|
+
`voice-agent/delegation-requested` is answered by one `commentary-added` carrying its
|
|
140
|
+
`delegationId`.
|
|
141
|
+
- **One verb pair per kind of change:**
|
|
142
|
+
- `added` / `removed` for membership in a set: `organization/member-added`,
|
|
143
|
+
`organization/project-added`, hostnames.
|
|
144
|
+
- `created` / `deleted` for an entity with a lifecycle: projects, repos, workspaces, agents.
|
|
145
|
+
- `set` / `deleted` for a keyed value: `secret/*`.
|
|
146
|
+
- `set` / `cancelled` for a schedule: `itx/schedule-*`. Each occurrence is `fired` or `failed`.
|
|
147
|
+
- `-configured` for one fact that sets a row or clears it with `null`
|
|
148
|
+
(`itx/subscription-configured`, `itx/rewrite-rule-configured`, `itx/fetch-route-configured`),
|
|
149
|
+
sets a singleton (`itx/ingress-configured`), or merges a partial configuration
|
|
150
|
+
(`agent/configured`: omitted keys keep their values).
|
|
151
|
+
- **Things the platform does on its own** are plain facts about the object: `itx/schedule-fired`,
|
|
152
|
+
`itx/schedule-failed`, `itx/subscription-delivery-halted`.
|
|
153
|
+
- **Ephemeral events.** An ephemeral event that records something happening is named like any other
|
|
154
|
+
fact: `itx/rpc-stub-attached`, `itx/live-state-changed`, `chrome/navigated`. Three kinds may be
|
|
155
|
+
singular nouns: a sequenced slice of a live stream is a `<stream>-frame`
|
|
156
|
+
(`voice-agent/mic-frame`, `agent/llm-response-frame`), a heartbeat (`voice-agent/keepalive`), and
|
|
157
|
+
a diagnostic record (`itx/alarm-trace`). A durable event is never a noun.
|
|
158
|
+
- **Families and prefixes.** Code matches some families by prefix: `…/itx/run-`,
|
|
159
|
+
`…/itx/subscription-`, `…/itx/schedule-`, `…/project/hostname-`. Before naming a new type, check
|
|
160
|
+
it doesn't join one of these families by accident. Never match `…/itx/` as a whole: it is not a
|
|
161
|
+
permission boundary, and it catches live-state deltas, stub presence and child
|
|
162
|
+
announcements.
|
|
163
|
+
- **Code follows the type.** A constant, schema, test fixture or idempotency key built from a type
|
|
164
|
+
follows its name (`itx/child-created:<path>`). Broader concepts, modules and Workers log
|
|
165
|
+
event names keep theirs: the Stream, scheduled appends, `core`, `scheduled-append.completed`.
|
|
166
|
+
- **Renaming.** A rename has to serve one of these rules, not taste. If a type is stored outside the
|
|
167
|
+
platform's Durable Objects (device firmware, a published SDK, a project's config repo),
|
|
168
|
+
rename it only in a change that migrates that store too.
|
|
169
|
+
|
|
170
|
+
| Namespace | Defined in |
|
|
171
|
+
| ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
172
|
+
| `itx` | `apps/os/src/stream/core-processor.ts` (and its leaf event catalog), `stream.ts`, `scheduled-appends.ts`, `subscription-delivery.ts`, `apps/os/src/context/built-ins.ts`, `apps/os/src/fetch-routes.ts`, `apps/os/src/iterate-context-durable-object.ts`, `packages/iterate/src/stream/{run,processor}.ts` |
|
|
173
|
+
| `account`, `organization`, `project`, `repo`, `workspace`, `secret` | `apps/os/src/<name>/contract.ts` (repo and workspace also use `project/entity-lifecycle.ts`) |
|
|
174
|
+
| `agent` | `apps/agents/runtime/contract.ts` |
|
|
175
|
+
| `voice-agent` | `apps/agents/voice/voice-agent.ts`, `apps/agents/voice/events.ts` |
|
|
176
|
+
| `chrome` | `apps/browser-extension/panel.js` |
|
|
177
|
+
| `test` | tests only |
|
|
178
|
+
|
|
179
|
+
Two types break these rules until the Kit firmware migrates:
|
|
180
|
+
|
|
181
|
+
- `voice-agent/spk-frame` will become `voice-agent/speaker-frame`.
|
|
182
|
+
- `voice-agent/conversation-ended` will become `voice-agent/call-ended`. It pairs with `call-started`
|
|
183
|
+
and names the activation; the provider session is the `conversation`.
|
|
184
|
+
|
|
185
|
+
`note/added` is only an example in the Agents composer; no contract defines `note`.
|
|
186
|
+
`email/received` is only an integration's transcript in an agent UI test; no contract defines
|
|
187
|
+
`email`.
|
|
188
|
+
`capability-host/script-run-*` is never written to a log: the agent UI's adapter builds it in
|
|
189
|
+
memory.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Ai } from "@cloudflare/workers-types";
|
|
2
|
-
import type {
|
|
2
|
+
import type { InvokeHandle, ItxExpression, ItxExpressionInput } from "./expression.ts";
|
|
3
3
|
import type { ConsentScope } from "./oauth-scopes.ts";
|
|
4
4
|
import type { Principal } from "./principal.ts";
|
|
5
5
|
import type { IngressRouting } from "./project-ingress.ts";
|
|
@@ -33,8 +33,8 @@ export type WaitForEventFilter = {
|
|
|
33
33
|
afterOffset?: number;
|
|
34
34
|
timeoutMs?: number;
|
|
35
35
|
};
|
|
36
|
-
/** The `rewrite-rule-configured` event's payload — what `
|
|
37
|
-
*
|
|
36
|
+
/** The `rewrite-rule-configured` event's payload — what `itx.append` writes durably and `provide`
|
|
37
|
+
* writes for its session: make `match` mean `target` (an expression, or `null` to deny). `description` is the one
|
|
38
38
|
* line a model reads for the name; it rides the row into `rewriteRules.list()`. */
|
|
39
39
|
export type RewriteRuleConfigured = {
|
|
40
40
|
match: ItxExpressionInput;
|
|
@@ -85,8 +85,8 @@ export type ScheduleReceipt = {
|
|
|
85
85
|
/** A secret's material: one string (`getSecret("/secrets/<name>")` is the whole value) or a JSON
|
|
86
86
|
* object whose string fields `getSecret("/secrets/<name>", { field: "a.b" })` picks — the
|
|
87
87
|
* multidimensional shape a credential exchange needs (`{ username, password, accessToken }`,
|
|
88
|
-
* `{ clientId, clientSecret, refreshToken, accessToken }`). A
|
|
89
|
-
*
|
|
88
|
+
* `{ clientId, clientSecret, refreshToken, accessToken }`). A string is always the one value: it has
|
|
89
|
+
* no fields, whether or not it parses as JSON. */
|
|
90
90
|
export type SecretMaterial = string | Record<string, unknown>;
|
|
91
91
|
/** How a token endpoint wants the client credential — the RFC 8414 `token_endpoint_auth_methods_supported`
|
|
92
92
|
* registry values, so a provider's discovery document pastes straight in: `client_secret_basic`
|
|
@@ -141,6 +141,47 @@ export type CollectSecretLink = {
|
|
|
141
141
|
path: string;
|
|
142
142
|
url: string;
|
|
143
143
|
};
|
|
144
|
+
/** WHICH requests a fetch route takes — every field given must hold: the host's routing slug
|
|
145
|
+
* (`blog` for `blog--<project>`), a `URLPattern` over the URL the app sees (its init's fields, each a
|
|
146
|
+
* pattern string), exact header values. `{}` takes every request. */
|
|
147
|
+
export type FetchRouteRequestMatcher = {
|
|
148
|
+
routingSlug?: string;
|
|
149
|
+
url?: {
|
|
150
|
+
protocol?: string;
|
|
151
|
+
username?: string;
|
|
152
|
+
password?: string;
|
|
153
|
+
hostname?: string;
|
|
154
|
+
port?: string;
|
|
155
|
+
pathname?: string;
|
|
156
|
+
search?: string;
|
|
157
|
+
hash?: string;
|
|
158
|
+
baseURL?: string;
|
|
159
|
+
};
|
|
160
|
+
headers?: Record<string, string>;
|
|
161
|
+
};
|
|
162
|
+
/** A route as `itx.fetchRoutes.set(name, route)` takes it: the requests it takes, the itx
|
|
163
|
+
* expression they go to, who may use it (`project-members`: the config worker answers anyone else
|
|
164
|
+
* the sign-in challenge; absent or null: public) and its priority (higher first, then by name). */
|
|
165
|
+
export type FetchRouteInput = {
|
|
166
|
+
requestMatcher: FetchRouteRequestMatcher;
|
|
167
|
+
target: ItxExpressionInput;
|
|
168
|
+
authRequirement?: {
|
|
169
|
+
visitors: "project-members";
|
|
170
|
+
} | null;
|
|
171
|
+
priority?: number;
|
|
172
|
+
};
|
|
173
|
+
/** A live route as `list()` and `match` answer it, its target parsed, with the offset of the
|
|
174
|
+
* `itx/fetch-route-configured` fact that set it. */
|
|
175
|
+
export type FetchRouteEntry = {
|
|
176
|
+
fetchRouteName: string;
|
|
177
|
+
requestMatcher: FetchRouteRequestMatcher;
|
|
178
|
+
target: ItxExpression;
|
|
179
|
+
authRequirement: {
|
|
180
|
+
visitors: "project-members";
|
|
181
|
+
} | null;
|
|
182
|
+
priority: number;
|
|
183
|
+
configuredOffset: number;
|
|
184
|
+
};
|
|
144
185
|
/** A context (a project, a user, an organization): every `itx` root, reached through `invoke`. */
|
|
145
186
|
export interface IterateContextApi {
|
|
146
187
|
invoke(call: ItxExpressionInput, ...args: unknown[]): Promise<unknown>;
|
|
@@ -176,6 +217,24 @@ export interface IterateContextApi {
|
|
|
176
217
|
projectUrl?: string;
|
|
177
218
|
}>;
|
|
178
219
|
append(...events: StreamEventInput[]): Promise<StreamEvent[]>;
|
|
220
|
+
/** This project's public URL over HTTP: the apex, or a routing slug's host (`blog--<project>`),
|
|
221
|
+
* at `path`. Only from a session, which carries the origin to compose it with. */
|
|
222
|
+
url(target?: {
|
|
223
|
+
routingSlug?: string;
|
|
224
|
+
path?: string;
|
|
225
|
+
}): Promise<string>;
|
|
226
|
+
/** RESET this context (Cloudflare's `ctx.abort`): its Durable Object drops everything it holds in
|
|
227
|
+
* memory and the next call starts a fresh incarnation from durable storage. Resolves with the
|
|
228
|
+
* `events.iterate.com/itx/aborted { reason?, callerPath?, app? }` event it recorded — durable
|
|
229
|
+
* and attributed to the caller before anything resets — and the reset follows the answer.
|
|
230
|
+
* SURVIVES: the log and everything derived from it (rewrite rules, subscriptions, schedules),
|
|
231
|
+
* every facet's storage, kv. GOES: in-memory state, every facet instance and its in-flight work,
|
|
232
|
+
* every socket on the context (a provider's re-dials), and every other call in flight there — it
|
|
233
|
+
* rejects with the reset's message (`itx.abort() reset the context <path>: <reason>`). A handle
|
|
234
|
+
* you kept names its target by expression, so its next call reaches the new incarnation.
|
|
235
|
+
* Another context of the project: `itx.cd(path).abort()`. A rewrite rule masks it like any name
|
|
236
|
+
* (`provide("itx.abort", null)`). */
|
|
237
|
+
abort(reason?: string): Promise<StreamEvent>;
|
|
179
238
|
readEvents(afterOffset?: number, limit?: number, options?: {
|
|
180
239
|
includeEphemeral?: boolean;
|
|
181
240
|
}): Promise<StreamPage>;
|
|
@@ -217,6 +276,21 @@ export interface IterateContextApi {
|
|
|
217
276
|
* from an agent context, a successful submission messages that same agent with the path only. */
|
|
218
277
|
collectFromUser(input: CollectSecretInput): Promise<CollectSecretLink>;
|
|
219
278
|
};
|
|
279
|
+
/** The project's fetch routes, on its root `/`: which requests on its hosts go to which itx
|
|
280
|
+
* expression. `set` appends one `itx/fetch-route-configured` fact (`null` deletes the route);
|
|
281
|
+
* `match` answers the route a request takes, which the config worker forwards with
|
|
282
|
+
* `env.ITX.fetch` naming `itx.fetchRoutes.fetch('<name>')` (a WebSocket upgrade included). */
|
|
283
|
+
fetchRoutes: {
|
|
284
|
+
set(fetchRouteName: string, route: FetchRouteInput | null): Promise<{
|
|
285
|
+
fetchRouteName: string;
|
|
286
|
+
}>;
|
|
287
|
+
list(): Promise<FetchRouteEntry[]>;
|
|
288
|
+
match(request: {
|
|
289
|
+
method: string;
|
|
290
|
+
url: string;
|
|
291
|
+
headers: Headers | Record<string, string> | [string, string][];
|
|
292
|
+
}): Promise<FetchRouteEntry | null>;
|
|
293
|
+
};
|
|
220
294
|
/** The table this context resolves against, described — the tree a model reads. `list()` follows a
|
|
221
295
|
* bare hop row into the context it names (a Durable Object hop, hence async). */
|
|
222
296
|
rewriteRules: {
|
|
@@ -224,13 +298,26 @@ export interface IterateContextApi {
|
|
|
224
298
|
get(match: string): Promise<RewriteRuleListEntry | null>;
|
|
225
299
|
resolve(call: ItxExpressionInput): string[];
|
|
226
300
|
};
|
|
301
|
+
/** A facet of this context: a caller reaches only what its class lists in `static publicMethods`
|
|
302
|
+
* (sdk/index.ts `FacetDurableObject`); anything else is refused FORBIDDEN. */
|
|
227
303
|
facets: {
|
|
228
|
-
get(name: string, spec?: FacetSpec):
|
|
304
|
+
get(name: string, spec?: FacetSpec): InvokeHandle;
|
|
305
|
+
/** RESET one facet of this context, from the context that hosts it — any facet, whether or not
|
|
306
|
+
* it extends the SDK's host, including one that would never answer a call. Its instance and
|
|
307
|
+
* in-memory state go, and every call in flight on it rejects `FACET_ABORTED`; its storage
|
|
308
|
+
* stays, and its next call starts it fresh. The context itself is not reset. Resolves with the
|
|
309
|
+
* `events.iterate.com/itx/facet-aborted { name, reason?, callerPath?, app? }` event;
|
|
310
|
+
* `NO_FACET` for a name never hosted here. */
|
|
311
|
+
abort(name: string, reason?: string): Promise<StreamEvent>;
|
|
229
312
|
};
|
|
230
313
|
subscriptions: {
|
|
231
314
|
list(): SubscriptionListEntry[];
|
|
232
315
|
get(name: string): SubscriptionListEntry | null;
|
|
233
316
|
};
|
|
317
|
+
/** The rpc stubs lent to this context right now, by key (a live session's `provide`). */
|
|
318
|
+
rpcStubs: {
|
|
319
|
+
list(): string[];
|
|
320
|
+
};
|
|
234
321
|
processors: {
|
|
235
322
|
enable(name: string, spec?: (FacetSpec & {
|
|
236
323
|
consumes?: string[];
|
|
@@ -263,18 +350,19 @@ export interface IterateContextApi {
|
|
|
263
350
|
}): Promise<{
|
|
264
351
|
[Symbol.dispose](): void;
|
|
265
352
|
}>;
|
|
266
|
-
/** A rewrite rule of this context, session-scoped (the handle's dispose removes it):
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
353
|
+
/** A rewrite rule of this context, session-scoped (the handle's dispose removes it): make `match`
|
|
354
|
+
* mean `target`, an expression, a live stub, or null to deny. `description` is the one line a
|
|
355
|
+
* model reads for the name. The durable spelling is the rule's event (`RewriteRuleConfigured`)
|
|
356
|
+
* through `itx.append`. */
|
|
357
|
+
provide(match: ItxExpressionInput, target: unknown, options?: {
|
|
358
|
+
description?: string;
|
|
359
|
+
}): Promise<{
|
|
273
360
|
[Symbol.dispose](): void;
|
|
274
361
|
}>;
|
|
275
362
|
/** A script — the text of `async (itx) => { … }` — run once against this context, on its log:
|
|
276
|
-
* `
|
|
277
|
-
* out); resolves with the result or rejects with the settlement's error. Never re-run.
|
|
363
|
+
* `itx/run-requested` under the caller, the context's runner, `run-settled` (JSON in, JSON
|
|
364
|
+
* out); resolves with the result or rejects with the settlement's error. Never re-run. A script
|
|
365
|
+
* still running ten minutes after it started is settled failed (`failureKind: "deadline"`). */
|
|
278
366
|
run(script: string): Promise<unknown>;
|
|
279
367
|
/** The project's repos, workspaces and agents as domain objects — one shape each: `get(path)` is
|
|
280
368
|
* the entity's facet on the context at `path` (its verbs, plus the typed `append` on that
|
|
@@ -343,21 +431,32 @@ export interface IterateContextApi {
|
|
|
343
431
|
}[]>;
|
|
344
432
|
};
|
|
345
433
|
}
|
|
346
|
-
/**
|
|
434
|
+
/** What a grant is: a sign-in not yet exchanged, a device's key, a personal access token, or a
|
|
435
|
+
* browser or app session. A client labels it for display. */
|
|
436
|
+
export type GrantKind = "pending" | "device" | "personal" | "session";
|
|
437
|
+
/** One grant as `grants.list()` shows it: a session or a connected app (an OAuth grant), or a
|
|
438
|
+
* personal access token or a device's key (the account's own API key, `pat_…`). */
|
|
347
439
|
export interface GrantRecord {
|
|
348
440
|
id: string;
|
|
349
441
|
clientId?: string;
|
|
350
442
|
logoUri?: string;
|
|
351
443
|
clientDomain?: string;
|
|
352
444
|
name: string;
|
|
353
|
-
kind:
|
|
445
|
+
kind: GrantKind;
|
|
446
|
+
/** An OAuth grant's one resource: Cap'n Web at `/api` (and the projects' hosts), or `/mcp`. A
|
|
447
|
+
* personal access token has none: it works at `/api`, at `/mcp` and on its projects' hosts. */
|
|
448
|
+
resource?: "api" | "mcp";
|
|
449
|
+
/** A personal access token's projects, by id: all it reaches. */
|
|
450
|
+
projects?: string[];
|
|
354
451
|
createdAt: number;
|
|
355
452
|
expiresAt: number | null;
|
|
356
453
|
lastUsedAt: number | null;
|
|
357
|
-
cleanupPending: boolean;
|
|
358
454
|
expired: boolean;
|
|
359
455
|
/** The grant this very session rides on. */
|
|
360
456
|
current?: boolean;
|
|
457
|
+
/** A personal access token's: the grant of the session that minted it (listed here while it
|
|
458
|
+
* lives). */
|
|
459
|
+
mintedBy?: string;
|
|
361
460
|
}
|
|
362
461
|
/** What the consent screen shows for an authorization request. */
|
|
363
462
|
export type ConsentAnswer = {
|
|
@@ -382,12 +481,20 @@ export type ConsentAnswer = {
|
|
|
382
481
|
kind: "invalid";
|
|
383
482
|
description: string;
|
|
384
483
|
};
|
|
484
|
+
/** An organization's invitation link as its owners see it (`expiresAt` ISO). */
|
|
485
|
+
export interface InvitationRecord {
|
|
486
|
+
id: string;
|
|
487
|
+
orgId: string;
|
|
488
|
+
role: "owner" | "member";
|
|
489
|
+
emailHint: string | null;
|
|
490
|
+
expiresAt: string;
|
|
491
|
+
}
|
|
385
492
|
/** An organization as the session lists it: its minted id, its free-text name, the person's role
|
|
386
493
|
* in it, and how many projects it holds (every one of them, not only those this grant lists). */
|
|
387
494
|
export interface OrgRecord {
|
|
388
495
|
id: string;
|
|
389
496
|
name: string;
|
|
390
|
-
role?:
|
|
497
|
+
role?: "owner" | "member";
|
|
391
498
|
projects: number;
|
|
392
499
|
}
|
|
393
500
|
/** A project as the catalog lists it: addressed by `id` everywhere (`projects.get`, a grant's list,
|
|
@@ -411,17 +518,9 @@ export interface IterateSessionApi {
|
|
|
411
518
|
/** the MCP server's origin (the dash's connect page) — "" when this deployment serves none */
|
|
412
519
|
mcpOrigin: string;
|
|
413
520
|
};
|
|
414
|
-
/** The
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
createOrg(name: string): Promise<OrgRecord>;
|
|
418
|
-
/** Rename an organization the person owns — `organizations:write`. */
|
|
419
|
-
updateOrg(orgId: string, input: {
|
|
420
|
-
name: string;
|
|
421
|
-
}): Promise<OrgRecord>;
|
|
422
|
-
/** Delete an organization the person owns, while it holds no project — `organizations:write`. */
|
|
423
|
-
deleteOrg(orgId: string): Promise<void>;
|
|
424
|
-
/** OAuth grants this session may manage (a signed-in person's): list, end, mint one for a device. */
|
|
521
|
+
/** The grants this session may manage (a signed-in person's with the `account` scope): list and
|
|
522
|
+
* end its sessions and personal access tokens, and mint a personal access token — its bearer
|
|
523
|
+
* answered once, `expiresAt` null for a key that never expires. */
|
|
425
524
|
grants: {
|
|
426
525
|
list(cursor?: string): Promise<{
|
|
427
526
|
items: GrantRecord[];
|
|
@@ -431,9 +530,18 @@ export interface IterateSessionApi {
|
|
|
431
530
|
}>;
|
|
432
531
|
end(grantId: string): Promise<unknown>;
|
|
433
532
|
endCurrent(): Promise<unknown>;
|
|
434
|
-
mint(input:
|
|
533
|
+
mint(input: {
|
|
534
|
+
name: string;
|
|
535
|
+
/** project ids, each one the person reaches */
|
|
536
|
+
projects: string[];
|
|
537
|
+
/** epoch ms; omitted, the key never expires */
|
|
538
|
+
expiresAt?: number;
|
|
539
|
+
/** a device's public client metadata document (Kit): the key is listed as that device */
|
|
540
|
+
clientId?: string;
|
|
541
|
+
}): Promise<{
|
|
542
|
+
id: string;
|
|
435
543
|
token: string;
|
|
436
|
-
expiresAt: number;
|
|
544
|
+
expiresAt: number | null;
|
|
437
545
|
}>;
|
|
438
546
|
};
|
|
439
547
|
/** The consent screen's methods (the OAuth authorize flow): describe a request, approve it. */
|
|
@@ -452,7 +560,8 @@ export interface IterateSessionApi {
|
|
|
452
560
|
list(): Promise<ProjectRecord[]>;
|
|
453
561
|
/** the project's root context, by its slug or its id */
|
|
454
562
|
get(project: string): Promise<IterateContextApi>;
|
|
455
|
-
/** Config repository presets available on this platform
|
|
563
|
+
/** Config repository presets available on this platform, besides the default config a
|
|
564
|
+
* creation that names no template gets. */
|
|
456
565
|
templates(): Promise<{
|
|
457
566
|
label: string;
|
|
458
567
|
reference: string;
|
|
@@ -467,8 +576,63 @@ export interface IterateSessionApi {
|
|
|
467
576
|
restoreProjectId?: string;
|
|
468
577
|
}): Promise<IterateContextApi>;
|
|
469
578
|
};
|
|
579
|
+
/** The organizations this session reaches — the person's memberships (a grant narrowed to
|
|
580
|
+
* projects sees only their organizations, unless it holds `organizations:write`): the rows, the
|
|
581
|
+
* organization's context by membership, and the verbs (`organizations:write`; the person is the
|
|
582
|
+
* owner of what they create, and only an owner renames, deletes or changes members). Each verb is
|
|
583
|
+
* a request the control plane answers; a refusal is a coded error (FORBIDDEN, INVALID_INPUT). */
|
|
470
584
|
organizations: {
|
|
585
|
+
list(): Promise<OrgRecord[]>;
|
|
586
|
+
/** the organization's context — `session.user` for an organization — by membership */
|
|
471
587
|
get(orgId: string): Promise<IterateContextApi>;
|
|
588
|
+
create(input: {
|
|
589
|
+
name: string;
|
|
590
|
+
}): Promise<OrgRecord>;
|
|
591
|
+
rename(orgId: string, input: {
|
|
592
|
+
name: string;
|
|
593
|
+
}): Promise<OrgRecord>;
|
|
594
|
+
/** only while it holds no project */
|
|
595
|
+
delete(orgId: string): Promise<void>;
|
|
596
|
+
addMember(orgId: string, input: {
|
|
597
|
+
userId: string;
|
|
598
|
+
role?: "owner" | "member";
|
|
599
|
+
}): Promise<void>;
|
|
600
|
+
removeMember(orgId: string, input: {
|
|
601
|
+
userId: string;
|
|
602
|
+
}): Promise<void>;
|
|
603
|
+
/** the members with their emails — the operator's alone (the project-seed CLI) */
|
|
604
|
+
members(orgId: string): Promise<{
|
|
605
|
+
userId: string;
|
|
606
|
+
email: string;
|
|
607
|
+
role: "owner" | "member";
|
|
608
|
+
}[]>;
|
|
609
|
+
/** an owner's invitation link: whoever accepts it first joins in `role` (default member),
|
|
610
|
+
* until it expires (`expiresInDays`, default 7, 1–30). `token` is the link's secret, answered
|
|
611
|
+
* this once — the dash's `/invitations/<token>`. */
|
|
612
|
+
createInvitation(orgId: string, input?: {
|
|
613
|
+
role?: "owner" | "member";
|
|
614
|
+
emailHint?: string;
|
|
615
|
+
expiresInDays?: number;
|
|
616
|
+
}): Promise<InvitationRecord & {
|
|
617
|
+
token: string;
|
|
618
|
+
}>;
|
|
619
|
+
/** an owner withdraws an open link by its id */
|
|
620
|
+
revokeInvitation(orgId: string, input: {
|
|
621
|
+
invitationId: string;
|
|
622
|
+
}): Promise<void>;
|
|
623
|
+
/** what a link opens, for the signed-in person holding it; null when it names nothing */
|
|
624
|
+
invitation(token: string): Promise<(InvitationRecord & {
|
|
625
|
+
orgName: string;
|
|
626
|
+
status: "pending" | "accepted" | "revoked" | "expired";
|
|
627
|
+
/** the reader already belongs */
|
|
628
|
+
member: boolean;
|
|
629
|
+
/** the reader is the one who accepted it — accepting again answers the same and lands
|
|
630
|
+
* the membership's facts again */
|
|
631
|
+
acceptedByYou: boolean;
|
|
632
|
+
}) | null>;
|
|
633
|
+
/** join the organization a link opens, in its role — single use: the first person to accept
|
|
634
|
+
* consumes it (again by them answers the same; anyone after is refused INVALID_INPUT) */
|
|
635
|
+
acceptInvitation(token: string): Promise<OrgRecord>;
|
|
472
636
|
};
|
|
473
637
|
user: IterateContextApi;
|
|
474
638
|
logout(): unknown;
|