@nylorun/runtime 0.19.1-beta → 0.20.0-beta
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/CHANGELOG.md +26 -0
- package/README.md +9 -5
- package/dist/adapters/streams/s2.js +5 -11
- package/dist/api/components.d.ts +171 -169
- package/dist/api/http/define.d.ts +3 -2
- package/dist/api/http/define.js +10 -11
- package/dist/api/openapi.js +31 -3
- package/dist/execution/types.d.ts +1 -1
- package/dist/host/app.d.ts +3 -0
- package/dist/host/app.js +33 -4
- package/dist/host/create-host.d.ts +6 -0
- package/dist/host/create-host.js +1 -0
- package/dist/host/main.js +11 -4
- package/dist/host/stack-config.js +1 -1
- package/dist/infra/index.d.ts +2 -1
- package/dist/infra/index.js +0 -1
- package/dist/infra/readiness.d.ts +6 -6
- package/dist/infra/readiness.js +2 -5
- package/dist/management-openapi.json +430 -107
- package/dist/openapi.json +366 -227
- package/dist/store/postgres/connect.d.ts +10 -0
- package/dist/store/postgres/connect.js +30 -3
- package/dist/store/postgres/control.d.ts +14 -0
- package/dist/store/postgres/control.js +187 -0
- package/dist/store/postgres/drizzle/0015_control_signals.sql +11 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +7 -0
- package/dist/store/postgres/schema.d.ts +120 -0
- package/dist/store/postgres/schema.js +20 -0
- package/dist/store/postgres/store.js +15 -0
- package/dist/store/types.d.ts +40 -0
- package/dist/streams/types.d.ts +6 -29
- package/dist/streams/types.js +5 -4
- package/dist/tenant/auth.d.ts +16 -6
- package/dist/tenant/auth.js +41 -17
- package/dist/tenant/commands.js +10 -6
- package/dist/tenant/context.d.ts +4 -0
- package/dist/tenant/control.d.ts +26 -0
- package/dist/tenant/control.js +35 -0
- package/dist/tenant/ephemeral.js +1 -0
- package/dist/tenant/http.d.ts +4 -2
- package/dist/tenant/http.js +4 -2
- package/dist/tenant/identity-file.d.ts +16 -12
- package/dist/tenant/identity-file.js +41 -29
- package/dist/tenant/issuers.d.ts +4 -3
- package/dist/tenant/issuers.js +22 -16
- package/dist/tenant/reset.d.ts +2 -2
- package/dist/tenant/reset.js +8 -2
- package/dist/tenant/resource-server.d.ts +56 -0
- package/dist/tenant/resource-server.js +62 -0
- package/dist/tenant/runtime.d.ts +1 -1
- package/dist/tenant/runtime.js +7 -1
- package/dist/tenant/scheduler.d.ts +1 -1
- package/dist/tenant/scheduler.js +1 -1
- package/dist/tenant/streams.d.ts +16 -22
- package/dist/tenant/streams.js +7 -87
- package/dist/tenant/sweep.js +9 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/streams/control.d.ts +0 -13
- package/dist/streams/control.js +0 -25
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.20.0-beta
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- cf5eb9c: **Protocol 9: the Runtime API is an OAuth 2.1 resource server for your identity provider's tokens.** Nylorun is still never the authorization server. Upgrade every package together; MIGRATION.md has the details.
|
|
8
|
+
|
|
9
|
+
- **Breaking (`@nylorun/runtime`): a refused credential is `401`, not the opaque `404`.** No `Authorization` is `401 credential_required`; an unknown key, or a token no trusted issuer signed or that fails a check, is `401 credential_invalid`. Each carries `WWW-Authenticate: Bearer` (OAuth 2.1 §5.3), naming the protected resource metadata (`resource_metadata`) on the Runtime API when the Runtime has trusted issuers; the Management API's challenge is a bare `Bearer`. `token_expired` and `issuer_unavailable` gain the challenge too. Another Tenant named, a Tenant that could not open and an unsigned capability link stay the opaque `404`.
|
|
10
|
+
- **Breaking (`@nylorun/runtime`): a request with neither `Nylorun-Protocol` nor `Authorization`** on an API route gets that route's `401` challenge instead of `426`, so a generic OAuth client learns where to sign in.
|
|
11
|
+
- `@nylorun/runtime`: a token without a route's scope still gets `403 scope_required`, now with `WWW-Authenticate: Bearer error="insufficient_scope", scope="…"`. The `Bearer` scheme is matched in any case (RFC 9110).
|
|
12
|
+
- `@nylorun/runtime`: `GET /.well-known/oauth-protected-resource` (RFC 9728) serves the resource (`NYLORUN_PUBLIC_URL`, else the request's origin), the identity file's issuers in order and their scopes, with no key or protocol; `404` without an identity file.
|
|
13
|
+
- **Breaking (`@nylorun/runtime`): the identity file drops `maxLifetime`.** The issuer sets its tokens' lifetimes; `exp` is required, `iat` no longer is. A key the file does not define, `maxLifetime` included, is ignored and logged (`identity_file_key_ignored`) instead of stopping the boot. `subject` defaults to `{sub}`, `scopes` to `{ claim: scope }` and `allowedScopes` to every token scope but `studio`.
|
|
14
|
+
- `@nylorun/core`: `PROTOCOL_VERSION` is 9 and `HOST_PROTOCOL` 4–9, with the required feature `resource-server`; `ERROR_CODES` adds `credential_required` and `credential_invalid`. `@nylorun/agents`, `@nylorun/admin` and `@nylorun/cli` send protocol 9.
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- 6711320: Cancels and sessions resets reach the other Runtime processes over a control bus on Postgres, not S2's `tenant/control` stream, which is gone: nothing inside the Runtime depends on S2 any more. A cancel writes a `session.cancel` signal in its own transaction and Postgres notifies every process at commit (`LISTEN`/`NOTIFY` on `nylorun_control`), so a cancel aborts the Worker's model or tool call even while S2 is down. Each process holds one `LISTEN` connection of its own and reads recent signals back every 5 s and after a reconnect; connect the Runtime to Postgres directly or through a pooler in session mode. Migration `0015_control_signals` adds `nylorun.control_signals`; the Tenant sweep deletes signals older than an hour. While processes of the previous beta still run beside new ones, a cancel between them is stopped by the Session Store check before the next effect, as when a signal was lost.
|
|
19
|
+
- 6711320: `/ready` no longer checks S2: its `checks` cover the listener, the Tenant, Postgres and Restate, and an unreachable S2 leaves it `200`. S2 only serves API listeners (history, SSE, AG-UI and A2A), so an outage degrades those reads and never makes the Runtime unready. S2's reachability stays in the Tenant's status (`GET /v1/tenant`, `streams.reachable`).
|
|
20
|
+
- 2ed5fe0: The event source `sandboxd` is now `sandboxes`, the name the sandbox lifecycle service took on 3 Oct, matching core, loop, gates, keys, egress and harness. Nothing emits it yet, so no stored event changes; the OpenAPI document's `EventSourceKind` enum shows the new name, and `--service sandboxes` is the blueprint service this release refuses as not yet shipped.
|
|
21
|
+
- Pin core to the tested release.
|
|
22
|
+
- Pin harness to the tested release.
|
|
23
|
+
- Updated dependencies [cf5eb9c]
|
|
24
|
+
- Updated dependencies [2ed5fe0]
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
- @nylorun/core@0.16.0-beta
|
|
27
|
+
- @nylorun/harness@0.23.1-beta
|
|
28
|
+
|
|
3
29
|
## 0.19.1-beta
|
|
4
30
|
|
|
5
31
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -136,7 +136,7 @@ The Host root is `NYLORUN_HOME` or `~/.nylorun` (for a local Tenant,
|
|
|
136
136
|
| Route | Auth | Notes |
|
|
137
137
|
| --- | --- | --- |
|
|
138
138
|
| `GET /health` | none | `service: "nylorun-runtime"`, `hostId`, protocol `{min,max,features}`, pid |
|
|
139
|
-
| `GET /ready` | none | Listener up, the Tenant open, and Postgres
|
|
139
|
+
| `GET /ready` | none | Listener up, the Tenant open, and Postgres and Restate answer (`checks`). S2 is not checked: its health is in `GET /v1/tenant` (`streams.reachable`); `harness: { mode, connected }` while the Tenant is open |
|
|
140
140
|
| `GET /openapi/runtime.json` | none | The Runtime API's OpenAPI 3.2 document (below); alias `GET /openapi.json`. Refuses an `Origin` |
|
|
141
141
|
| `GET /openapi/management.json` | none | The Management API's OpenAPI 3.2 document. Refuses an `Origin` |
|
|
142
142
|
| `/v1/*` Runtime API routes (all but `/v1/tenant/*`) | application key or trusted issuer's token | Require `Nylorun-Protocol`; nothing names the Tenant. A management key is `403 key_role_mismatch`, except on `/v1/me` and the public `GET /v1/access/jwks` |
|
|
@@ -154,15 +154,19 @@ presents a trusted issuer's token; keys (application and management)
|
|
|
154
154
|
are refused from browsers before they are looked up. The Runtime sends no CORS headers, and answers
|
|
155
155
|
`OPTIONS` with `204` and `Allow` only: the operator's reverse proxy answers preflights
|
|
156
156
|
([DEPLOYMENT.md](../DEPLOYMENT.md#calling-the-runtime-from-browsers-and-apps)). Missing or
|
|
157
|
-
unsupported protocol → `426` before authentication
|
|
158
|
-
|
|
157
|
+
unsupported protocol → `426` before authentication, unless the request sends neither
|
|
158
|
+
`Nylorun-Protocol` nor `Authorization` (the Host serves protocols 4 to 9; protocol 9 makes the
|
|
159
|
+
Runtime API an OAuth 2.1 resource server: a missing or rejected credential is `401
|
|
160
|
+
credential_required` or `credential_invalid` with a `WWW-Authenticate: Bearer` challenge, a
|
|
161
|
+
token without a route's scope gets `error="insufficient_scope"`, and
|
|
162
|
+
`/.well-known/oauth-protected-resource` lists the trusted issuers (RFC 9728); protocol 8 gives keys roles, moves vaults and signing keys under `/v1/tenant` and removes
|
|
159
163
|
the Admin API, and those old paths answer `404` with no alias; protocol 7 removes subject tokens, the access policy, revocations, browser keys and
|
|
160
164
|
derived principals, whose routes answer `404`; protocol 6 adds file and folder artifacts and message `parts`; at each turn's end the
|
|
161
165
|
Runtime exports `/workspace/outputs` of the session's sandbox as a version of its
|
|
162
166
|
`outputs` folder, read at `/v1/artifacts/{id}/versions/{n|latest}/tree`, `/files/{path}`,
|
|
163
167
|
`/diff?from=` and `/zip`). Protocol 5 and later clients name no Tenant. A protocol 4 client's `Nylorun-Tenant` naming
|
|
164
|
-
another Tenant (or malformed)
|
|
165
|
-
could not be opened
|
|
168
|
+
another Tenant (or malformed) and a Tenant that
|
|
169
|
+
could not be opened → opaque `404` with identical body. A path or method no route serves is `404 Route not found`
|
|
166
170
|
once the caller is known.
|
|
167
171
|
|
|
168
172
|
## API reference (OpenAPI)
|
|
@@ -8,10 +8,9 @@
|
|
|
8
8
|
* - One basin per Tenant basin generation, named by `tenantBasinName` (`streams/basin.ts`):
|
|
9
9
|
* `<basinPrefix>tn-<ulid>` for a Tenant id `tn_<ulid>`, `…-<g base36>` for generation g.
|
|
10
10
|
* - The basin is created with `createStreamOnAppend` and `createStreamOnRead`, so
|
|
11
|
-
* `sessions/<id>`
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* age-based retention instead (signals are latency hints, not history).
|
|
11
|
+
* `sessions/<id>` come into existence on first use. Its default stream config
|
|
12
|
+
* sets infinite retention, which session streams keep. There are no other
|
|
13
|
+
* streams: signals between processes go over Postgres (D48).
|
|
15
14
|
* - Bodies are JSON text in string records. Record timestamps are S2 arrival
|
|
16
15
|
* times.
|
|
17
16
|
* - Appends use `appendRetryPolicy: "noSideEffects"`: the SDK retries only
|
|
@@ -27,7 +26,7 @@
|
|
|
27
26
|
* explicit `{ infinite: {} }` retention to keep session history; this adapter
|
|
28
27
|
* sets it as the basin default, and s2-lite honours it (a new stream reports
|
|
29
28
|
* `infinite`). A `streamConfig` sent with an append that creates the stream
|
|
30
|
-
* is honoured too
|
|
29
|
+
* is honoured too. `deleteOnEmpty`
|
|
31
30
|
* defaults to disabled (`minAgeSecs: 0`).
|
|
32
31
|
* - **Stream deletion** is immediate for our purposes: right after `DELETE`,
|
|
33
32
|
* `checkTail` and reads return 404 `stream_not_found` (new read sessions
|
|
@@ -59,9 +58,7 @@
|
|
|
59
58
|
*/
|
|
60
59
|
import { AppendInput, AppendRecord, RangeNotSatisfiableError, S2, S2Error, SeqNumMismatchError, } from "@s2-dev/streamstore";
|
|
61
60
|
import { parseBasin, tenantBasinName, validateBasinPrefix } from "../../streams/basin.js";
|
|
62
|
-
import {
|
|
63
|
-
/** Retention of the control signal stream. */
|
|
64
|
-
const SIGNAL_RETENTION_SECS = 24 * 60 * 60;
|
|
61
|
+
import {} from "../../streams/types.js";
|
|
65
62
|
/** Records per unary read while reading history. */
|
|
66
63
|
const HISTORY_PAGE = 1000;
|
|
67
64
|
const RETRY_MIN_MS = 100;
|
|
@@ -99,9 +96,6 @@ class S2Streams {
|
|
|
99
96
|
return AppendRecord.string({ body });
|
|
100
97
|
}), {
|
|
101
98
|
...(options.matchSeq !== undefined ? { matchSeqNum: options.matchSeq } : {}),
|
|
102
|
-
...(stream === CONTROL_STREAM
|
|
103
|
-
? { streamConfig: { retentionPolicy: { ageSecs: SIGNAL_RETENTION_SECS } } }
|
|
104
|
-
: {}),
|
|
105
99
|
});
|
|
106
100
|
const handle = this.handle(tenantId, stream);
|
|
107
101
|
let delay = RETRY_MIN_MS / 4;
|