@nylorun/runtime 0.14.0-beta → 0.15.1-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.
Files changed (198) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +82 -40
  3. package/dist/adapters/execution/restate.js +2 -2
  4. package/dist/adapters/replication/pgoutput.d.ts +5 -0
  5. package/dist/adapters/replication/pgoutput.js +4 -3
  6. package/dist/admin-openapi.json +185 -686
  7. package/dist/api/components.d.ts +308 -68
  8. package/dist/api/components.js +4 -5
  9. package/dist/api/gate/keys.d.ts +14 -0
  10. package/dist/api/gate/keys.js +59 -0
  11. package/dist/api/gate/routes.d.ts +34 -0
  12. package/dist/api/gate/routes.js +235 -0
  13. package/dist/api/http/define.js +0 -8
  14. package/dist/api/http/routes/access.js +25 -18
  15. package/dist/api/http/routes/tenant.d.ts +2 -1
  16. package/dist/api/http/routes/tenant.js +77 -5
  17. package/dist/api/http/routes/vaults.js +2 -2
  18. package/dist/api/openapi.js +6 -7
  19. package/dist/gates/contract.d.ts +51 -0
  20. package/dist/gates/contract.js +37 -0
  21. package/dist/gates/handler.d.ts +21 -0
  22. package/dist/gates/handler.js +55 -0
  23. package/dist/gates/http-client.d.ts +12 -0
  24. package/dist/gates/http-client.js +160 -0
  25. package/dist/gates/in-process.d.ts +32 -0
  26. package/dist/gates/in-process.js +42 -0
  27. package/dist/gates/inflight.d.ts +39 -0
  28. package/dist/gates/inflight.js +70 -0
  29. package/dist/gates/mcp-handler.d.ts +35 -0
  30. package/dist/gates/mcp-handler.js +142 -0
  31. package/dist/gates/meter.d.ts +24 -0
  32. package/dist/gates/meter.js +165 -0
  33. package/dist/gates/model-gate.d.ts +45 -0
  34. package/dist/gates/model-gate.js +1 -0
  35. package/dist/gates/tenant-vaults.d.ts +64 -0
  36. package/dist/gates/tenant-vaults.js +94 -0
  37. package/dist/gates/tool-calls.d.ts +51 -0
  38. package/dist/gates/tool-calls.js +64 -0
  39. package/dist/gates/tool-client.d.ts +12 -0
  40. package/dist/gates/tool-client.js +201 -0
  41. package/dist/gates/tool-contract.d.ts +116 -0
  42. package/dist/gates/tool-contract.js +64 -0
  43. package/dist/gates/tool-gate.d.ts +45 -0
  44. package/dist/gates/tool-gate.js +10 -0
  45. package/dist/host/admin-api.d.ts +7 -6
  46. package/dist/host/admin-api.js +9 -113
  47. package/dist/host/app.d.ts +1 -1
  48. package/dist/host/app.js +20 -24
  49. package/dist/host/config-for.d.ts +1 -1
  50. package/dist/host/config-for.js +2 -2
  51. package/dist/host/create-host.d.ts +5 -5
  52. package/dist/host/create-host.js +5 -15
  53. package/dist/host/execution.d.ts +20 -18
  54. package/dist/host/execution.js +2 -2
  55. package/dist/host/gates.d.ts +58 -0
  56. package/dist/host/gates.js +127 -0
  57. package/dist/host/http.d.ts +6 -1
  58. package/dist/host/http.js +17 -0
  59. package/dist/host/index.d.ts +1 -1
  60. package/dist/host/main.js +151 -71
  61. package/dist/host/stack-config.d.ts +71 -19
  62. package/dist/host/stack-config.js +192 -18
  63. package/dist/infra/database.d.ts +2 -2
  64. package/dist/infra/execution.d.ts +5 -5
  65. package/dist/infra/execution.js +8 -6
  66. package/dist/infra/index.d.ts +1 -1
  67. package/dist/infra/workers.d.ts +17 -17
  68. package/dist/infra/workers.js +9 -9
  69. package/dist/keys/client.d.ts +9 -0
  70. package/dist/keys/client.js +70 -0
  71. package/dist/keys/contract.d.ts +24 -0
  72. package/dist/keys/contract.js +12 -0
  73. package/dist/keys/keys.d.ts +41 -0
  74. package/dist/keys/keys.js +50 -0
  75. package/dist/mcp/connect.d.ts +43 -3
  76. package/dist/mcp/connect.js +12 -5
  77. package/dist/mcp/pool.d.ts +21 -3
  78. package/dist/mcp/pool.js +15 -2
  79. package/dist/openapi.json +888 -695
  80. package/dist/record/append.d.ts +51 -0
  81. package/dist/record/append.js +20 -0
  82. package/dist/{store/event.js → record/envelope.js} +1 -1
  83. package/dist/record/index.d.ts +11 -0
  84. package/dist/record/index.js +11 -0
  85. package/dist/store/postgres/connect.d.ts +15 -12
  86. package/dist/store/postgres/connect.js +24 -12
  87. package/dist/store/postgres/db.d.ts +16 -0
  88. package/dist/store/postgres/db.js +28 -0
  89. package/dist/store/postgres/drizzle/0000_foundation.sql +22 -0
  90. package/dist/store/postgres/drizzle/0001_baseline.sql +255 -0
  91. package/dist/store/postgres/drizzle/0002_stream_relay.sql +4 -0
  92. package/dist/store/postgres/drizzle/0003_tool_crossings.sql +9 -0
  93. package/dist/store/postgres/drizzle/meta/_journal.json +34 -0
  94. package/dist/store/postgres/migrate.d.ts +68 -0
  95. package/dist/store/postgres/migrate.js +183 -0
  96. package/dist/store/postgres/record-writer.d.ts +4 -0
  97. package/dist/store/postgres/record-writer.js +34 -0
  98. package/dist/store/postgres/record.d.ts +2 -8
  99. package/dist/store/postgres/record.js +50 -54
  100. package/dist/store/postgres/schema.d.ts +3096 -0
  101. package/dist/store/postgres/schema.js +363 -0
  102. package/dist/store/postgres/store.d.ts +2 -4
  103. package/dist/store/postgres/store.js +481 -567
  104. package/dist/store/postgres/tenant.d.ts +56 -0
  105. package/dist/store/postgres/tenant.js +154 -0
  106. package/dist/store/types.d.ts +43 -87
  107. package/dist/store/types.js +0 -1
  108. package/dist/streams/control.d.ts +1 -1
  109. package/dist/streams/control.js +6 -2
  110. package/dist/streams/relay/types.d.ts +2 -1
  111. package/dist/streams/relay/types.js +2 -1
  112. package/dist/streams/types.d.ts +5 -0
  113. package/dist/tenant/advance.d.ts +7 -2
  114. package/dist/tenant/advance.js +95 -16
  115. package/dist/tenant/cause.d.ts +25 -0
  116. package/dist/tenant/cause.js +45 -0
  117. package/dist/tenant/commands.js +4 -2
  118. package/dist/tenant/context.d.ts +26 -3
  119. package/dist/tenant/delivery-token.js +17 -18
  120. package/dist/tenant/delivery.d.ts +1 -1
  121. package/dist/tenant/delivery.js +18 -13
  122. package/dist/tenant/effects.d.ts +15 -1
  123. package/dist/tenant/effects.js +93 -17
  124. package/dist/tenant/ephemeral.d.ts +16 -7
  125. package/dist/tenant/ephemeral.js +45 -111
  126. package/dist/tenant/history.d.ts +64 -0
  127. package/dist/tenant/history.js +120 -0
  128. package/dist/tenant/model-setting.d.ts +2 -2
  129. package/dist/tenant/module.d.ts +14 -28
  130. package/dist/tenant/module.js +131 -271
  131. package/dist/tenant/paths.d.ts +11 -16
  132. package/dist/tenant/paths.js +24 -68
  133. package/dist/tenant/pool.d.ts +1 -1
  134. package/dist/tenant/pool.js +1 -1
  135. package/dist/tenant/principals.d.ts +23 -11
  136. package/dist/tenant/principals.js +61 -49
  137. package/dist/tenant/runtime.d.ts +19 -1
  138. package/dist/tenant/runtime.js +40 -26
  139. package/dist/tenant/scheduler.d.ts +4 -2
  140. package/dist/tenant/scheduler.js +4 -4
  141. package/dist/tenant/session-streams.d.ts +2 -0
  142. package/dist/tenant/session-streams.js +8 -3
  143. package/dist/tenant/status.d.ts +3 -0
  144. package/dist/tenant/status.js +1 -1
  145. package/dist/tenant/store-pg.d.ts +9 -6
  146. package/dist/tenant/store-pg.js +60 -125
  147. package/dist/tenant/streams.d.ts +9 -25
  148. package/dist/tenant/streams.js +7 -22
  149. package/dist/tenant/tokens.js +16 -14
  150. package/dist/tenant/types.d.ts +41 -92
  151. package/dist/tenant/types.js +4 -15
  152. package/dist/tenant/worker.js +4 -4
  153. package/dist/vault/host-model.d.ts +31 -0
  154. package/dist/vault/host-model.js +57 -0
  155. package/dist/vault/service.d.ts +26 -15
  156. package/dist/vault/service.js +70 -109
  157. package/dist/version.d.ts +1 -1
  158. package/dist/version.js +1 -1
  159. package/package.json +9 -5
  160. package/dist/store/memory.d.ts +0 -69
  161. package/dist/store/memory.js +0 -810
  162. package/dist/store/postgres/migrations/001_initial.d.ts +0 -27
  163. package/dist/store/postgres/migrations/001_initial.js +0 -196
  164. package/dist/store/postgres/migrations/002_session_owner.d.ts +0 -6
  165. package/dist/store/postgres/migrations/002_session_owner.js +0 -13
  166. package/dist/store/postgres/migrations/003_subject_tokens.d.ts +0 -8
  167. package/dist/store/postgres/migrations/003_subject_tokens.js +0 -42
  168. package/dist/store/postgres/migrations/004_publishable_keys.d.ts +0 -6
  169. package/dist/store/postgres/migrations/004_publishable_keys.js +0 -18
  170. package/dist/store/postgres/migrations/005_action_endpoints.d.ts +0 -6
  171. package/dist/store/postgres/migrations/005_action_endpoints.js +0 -32
  172. package/dist/store/postgres/migrations/006_drop_executors.d.ts +0 -11
  173. package/dist/store/postgres/migrations/006_drop_executors.js +0 -32
  174. package/dist/store/postgres/migrations/007_event_time.d.ts +0 -7
  175. package/dist/store/postgres/migrations/007_event_time.js +0 -14
  176. package/dist/store/postgres/migrations/008_durable_streams.d.ts +0 -13
  177. package/dist/store/postgres/migrations/008_durable_streams.js +0 -35
  178. package/dist/store/postgres/migrations/index.d.ts +0 -53
  179. package/dist/store/postgres/migrations/index.js +0 -96
  180. package/dist/store/postgres/migrations/shared/index.d.ts +0 -31
  181. package/dist/store/postgres/migrations/shared/index.js +0 -92
  182. package/dist/store/postgres/names.d.ts +0 -11
  183. package/dist/store/postgres/names.js +0 -42
  184. package/dist/store/postgres/tenants.d.ts +0 -90
  185. package/dist/store/postgres/tenants.js +0 -228
  186. package/dist/streams/relay/memory.d.ts +0 -69
  187. package/dist/streams/relay/memory.js +0 -176
  188. package/dist/tenant/envelope.d.ts +0 -7
  189. package/dist/tenant/envelope.js +0 -22
  190. package/dist/tenant/quarantine-error.d.ts +0 -6
  191. package/dist/tenant/quarantine-error.js +0 -9
  192. package/dist/tenant/quarantine.d.ts +0 -27
  193. package/dist/tenant/quarantine.js +0 -72
  194. package/dist/tenant/store-memory.d.ts +0 -16
  195. package/dist/tenant/store-memory.js +0 -111
  196. /package/dist/{store → record}/cursor.d.ts +0 -0
  197. /package/dist/{store → record}/cursor.js +0 -0
  198. /package/dist/{store/event.d.ts → record/envelope.d.ts} +0 -0
@@ -1,27 +0,0 @@
1
- import type { Migration } from "./index.js";
2
- /**
3
- * The first Postgres Tenant schema.
4
- *
5
- * - `tenant` holds the Tenant envelope (one row).
6
- * - Document tables keep `id text primary key, body json`. The fields typed
7
- * queries filter on are stored generated columns with indexes. Ids and
8
- * timestamps compared as text use `COLLATE "C"`, so ordering is by code
9
- * point, like the in-memory fake, whatever the database collation.
10
- * - Bodies are `json`, not `jsonb`, so every string round-trips exactly as
11
- * `JSON.stringify` wrote it. `jsonb` rejects the escapes `\u0000` (`22P05`)
12
- * and unpaired surrogates (`\ud800`), which tool output can contain and
13
- * which the in-memory store accepts. `json` stores the text
14
- * verbatim and checks only its syntax. The generated columns read the body
15
- * through `doc(body)`, which casts to `jsonb` after replacing those two
16
- * escapes with `\ufffd`: the stored body is untouched, and only an indexed
17
- * field that itself contained one (never an id, status or timestamp) would
18
- * see U+FFFD. Bodies with no `\u` escape at all take the plain cast. Queries
19
- * never apply `->`/`->>` to a `json` body (Postgres de-escapes the whole text
20
- * and fails on the same escapes); they read generated columns.
21
- * - `sessions` carries the store-managed `next_event_seq` and ownership
22
- * columns (`owner`, `epoch`, `owner_expires_at`), which are never in `body`.
23
- * - `outbox(session_id, seq, body)` holds committed, unrelayed events.
24
- * - Executors, principals, vault and settings keep typed columns. Vault
25
- * ciphertext is `bytea` columns, never inside a JSON body.
26
- */
27
- export declare const initial: Migration;
@@ -1,196 +0,0 @@
1
- /**
2
- * The first Postgres Tenant schema.
3
- *
4
- * - `tenant` holds the Tenant envelope (one row).
5
- * - Document tables keep `id text primary key, body json`. The fields typed
6
- * queries filter on are stored generated columns with indexes. Ids and
7
- * timestamps compared as text use `COLLATE "C"`, so ordering is by code
8
- * point, like the in-memory fake, whatever the database collation.
9
- * - Bodies are `json`, not `jsonb`, so every string round-trips exactly as
10
- * `JSON.stringify` wrote it. `jsonb` rejects the escapes `\u0000` (`22P05`)
11
- * and unpaired surrogates (`\ud800`), which tool output can contain and
12
- * which the in-memory store accepts. `json` stores the text
13
- * verbatim and checks only its syntax. The generated columns read the body
14
- * through `doc(body)`, which casts to `jsonb` after replacing those two
15
- * escapes with `\ufffd`: the stored body is untouched, and only an indexed
16
- * field that itself contained one (never an id, status or timestamp) would
17
- * see U+FFFD. Bodies with no `\u` escape at all take the plain cast. Queries
18
- * never apply `->`/`->>` to a `json` body (Postgres de-escapes the whole text
19
- * and fails on the same escapes); they read generated columns.
20
- * - `sessions` carries the store-managed `next_event_seq` and ownership
21
- * columns (`owner`, `epoch`, `owner_expires_at`), which are never in `body`.
22
- * - `outbox(session_id, seq, body)` holds committed, unrelayed events.
23
- * - Executors, principals, vault and settings keep typed columns. Vault
24
- * ciphertext is `bytea` columns, never inside a JSON body.
25
- */
26
- export const initial = {
27
- version: 1,
28
- name: "initial",
29
- up: (s) => `
30
- CREATE FUNCTION ${s}.doc(body json) RETURNS jsonb
31
- LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS $$
32
- SELECT CASE WHEN strpos(body::text, '\\u') = 0 THEN body::jsonb
33
- ELSE regexp_replace(
34
- body::text,
35
- '(?<!\\\\)((?:\\\\\\\\)*)\\\\u(0000|[dD][89a-fA-F][0-9a-fA-F]{2})',
36
- '\\1\\\\ufffd',
37
- 'g'
38
- )::jsonb
39
- END
40
- $$;
41
-
42
- CREATE TABLE ${s}.tenant (
43
- id text COLLATE "C" PRIMARY KEY,
44
- name text NOT NULL,
45
- created_at text NOT NULL,
46
- updated_at text NOT NULL,
47
- schema_version integer NOT NULL,
48
- singleton boolean NOT NULL DEFAULT true UNIQUE CHECK (singleton)
49
- );
50
-
51
- CREATE TABLE ${s}.definitions (
52
- id text COLLATE "C" PRIMARY KEY,
53
- body json NOT NULL
54
- );
55
-
56
- CREATE TABLE ${s}.sessions (
57
- id text COLLATE "C" PRIMARY KEY,
58
- body json NOT NULL,
59
- status text GENERATED ALWAYS AS (${s}.doc(body)->>'status') STORED,
60
- agent_id text GENERATED ALWAYS AS (${s}.doc(body)->>'agentId') STORED,
61
- stream_incarnation text GENERATED ALWAYS AS (${s}.doc(body)->>'streamIncarnation') STORED,
62
- next_event_seq bigint NOT NULL DEFAULT 0,
63
- owner text,
64
- epoch bigint NOT NULL DEFAULT 0,
65
- owner_expires_at timestamptz
66
- );
67
- CREATE INDEX sessions_status ON ${s}.sessions (status, owner_expires_at);
68
- CREATE INDEX sessions_agent ON ${s}.sessions (agent_id);
69
-
70
- CREATE TABLE ${s}.commands (
71
- id text COLLATE "C" PRIMARY KEY,
72
- body json NOT NULL
73
- );
74
-
75
- CREATE TABLE ${s}.checkpoints (
76
- id text COLLATE "C" PRIMARY KEY,
77
- body json NOT NULL
78
- );
79
-
80
- CREATE TABLE ${s}.effects (
81
- id text COLLATE "C" PRIMARY KEY,
82
- body json NOT NULL,
83
- session_id text GENERATED ALWAYS AS (${s}.doc(body)->'request'->>'sessionId') STORED,
84
- turn_id text GENERATED ALWAYS AS (${s}.doc(body)->'request'->>'turnId') STORED,
85
- kind text GENERATED ALWAYS AS (${s}.doc(body)->'request'->>'kind') STORED,
86
- status text GENERATED ALWAYS AS (${s}.doc(body)->>'status') STORED
87
- );
88
- CREATE INDEX effects_session ON ${s}.effects (session_id, turn_id, status);
89
- CREATE INDEX effects_status ON ${s}.effects (status, kind);
90
-
91
- CREATE TABLE ${s}.actions (
92
- id text COLLATE "C" PRIMARY KEY,
93
- body json NOT NULL,
94
- session_id text GENERATED ALWAYS AS (${s}.doc(body)->>'sessionId') STORED,
95
- turn_id text GENERATED ALWAYS AS (${s}.doc(body)->>'turnId') STORED,
96
- agent_id text GENERATED ALWAYS AS (${s}.doc(body)->>'agentId') STORED,
97
- status text GENERATED ALWAYS AS (${s}.doc(body)->>'status') STORED,
98
- kind text GENERATED ALWAYS AS (${s}.doc(body)->>'kind') STORED,
99
- lease_expires_at text GENERATED ALWAYS AS (${s}.doc(body)->>'leaseExpiresAt') STORED
100
- );
101
- CREATE INDEX actions_session ON ${s}.actions (session_id, turn_id, status);
102
- CREATE INDEX actions_agent ON ${s}.actions (agent_id, status);
103
- CREATE INDEX actions_status ON ${s}.actions (status, kind);
104
- CREATE INDEX actions_lease ON ${s}.actions (status, lease_expires_at);
105
-
106
- CREATE TABLE ${s}.sandboxes (
107
- id text COLLATE "C" PRIMARY KEY,
108
- body json NOT NULL
109
- );
110
-
111
- CREATE TABLE ${s}.links (
112
- id text COLLATE "C" PRIMARY KEY,
113
- body json NOT NULL,
114
- workflow_session_id text GENERATED ALWAYS AS (${s}.doc(body)->>'workflowSessionId') STORED
115
- );
116
- CREATE INDEX links_workflow ON ${s}.links (workflow_session_id);
117
-
118
- CREATE TABLE ${s}.outbox (
119
- session_id text COLLATE "C" NOT NULL,
120
- seq bigint NOT NULL,
121
- body json NOT NULL,
122
- created_at text COLLATE "C" GENERATED ALWAYS AS (${s}.doc(body)->>'createdAt') STORED,
123
- PRIMARY KEY (session_id, seq)
124
- );
125
-
126
- CREATE TABLE ${s}.executors (
127
- agent_id text COLLATE "C" PRIMARY KEY,
128
- token_hash text NOT NULL UNIQUE,
129
- implementation_version text NOT NULL,
130
- manifest_hash text,
131
- principal_id text,
132
- created_at text NOT NULL,
133
- updated_at text NOT NULL
134
- );
135
-
136
- CREATE TABLE ${s}.principals (
137
- id text COLLATE "C" PRIMARY KEY,
138
- role text NOT NULL,
139
- token_hash text NOT NULL UNIQUE,
140
- idempotency_key text,
141
- created_at text NOT NULL
142
- );
143
-
144
- CREATE TABLE ${s}.vaults (
145
- id text COLLATE "C" PRIMARY KEY,
146
- name text NOT NULL,
147
- owner_user_id text NOT NULL,
148
- metadata_json text,
149
- created_at text COLLATE "C" NOT NULL,
150
- scope text NOT NULL DEFAULT 'user' CHECK (scope IN ('user', 'host'))
151
- );
152
- CREATE INDEX vaults_owner ON ${s}.vaults (owner_user_id, created_at, id);
153
- CREATE UNIQUE INDEX vaults_one_host ON ${s}.vaults (scope) WHERE scope = 'host';
154
-
155
- CREATE TABLE ${s}.vault_credentials (
156
- id text COLLATE "C" PRIMARY KEY,
157
- vault_id text NOT NULL REFERENCES ${s}.vaults (id) ON DELETE CASCADE,
158
- name text NOT NULL,
159
- type text NOT NULL,
160
- binding_json text NOT NULL,
161
- expires_at text,
162
- created_at text COLLATE "C" NOT NULL,
163
- rotated_at text,
164
- kek_id text NOT NULL,
165
- nonce bytea NOT NULL,
166
- ciphertext bytea NOT NULL,
167
- wrapped_dek bytea NOT NULL
168
- );
169
- CREATE INDEX vault_credentials_vault ON ${s}.vault_credentials (vault_id, created_at, id);
170
-
171
- CREATE TABLE ${s}.vault_audit (
172
- ord bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
173
- id text NOT NULL UNIQUE,
174
- at text NOT NULL,
175
- actor text NOT NULL,
176
- action text NOT NULL,
177
- vault_id text,
178
- credential_id text,
179
- session_id text,
180
- target text,
181
- outcome text NOT NULL
182
- );
183
- CREATE INDEX vault_audit_vault ON ${s}.vault_audit (vault_id, ord);
184
-
185
- CREATE TABLE ${s}.vault_idempotency (
186
- id text PRIMARY KEY,
187
- body_hash text NOT NULL,
188
- response text NOT NULL
189
- );
190
-
191
- CREATE TABLE ${s}.tenant_settings (
192
- key text PRIMARY KEY,
193
- value text NOT NULL
194
- );
195
- `,
196
- };
@@ -1,6 +0,0 @@
1
- import type { Migration } from "./index.js";
2
- /**
3
- * The session owner (`ownerUserId`) as a stored generated column with an index, so a request
4
- * acting for a subject lists only that subject's sessions. Not the lease column `owner`.
5
- */
6
- export declare const sessionOwner: Migration;
@@ -1,13 +0,0 @@
1
- /**
2
- * The session owner (`ownerUserId`) as a stored generated column with an index, so a request
3
- * acting for a subject lists only that subject's sessions. Not the lease column `owner`.
4
- */
5
- export const sessionOwner = {
6
- version: 2,
7
- name: "session_owner",
8
- up: (s) => `
9
- ALTER TABLE ${s}.sessions
10
- ADD COLUMN owner_user_id text GENERATED ALWAYS AS (${s}.doc(body)->>'ownerUserId') STORED;
11
- CREATE INDEX sessions_owner_user ON ${s}.sessions (owner_user_id);
12
- `,
13
- };
@@ -1,8 +0,0 @@
1
- import type { Migration } from "./index.js";
2
- /**
3
- * Subject tokens (Host feature `subject-tokens`): the Tenant's signing keys (private halves
4
- * sealed with the vault KEK, like credentials), each subject's revocation epoch, each
5
- * subject's turn bucket. Counting a subject's sessions by status uses the owner index of
6
- * migration 2; a second index on status would be written on every session transition.
7
- */
8
- export declare const subjectTokens: Migration;
@@ -1,42 +0,0 @@
1
- /**
2
- * Subject tokens (Host feature `subject-tokens`): the Tenant's signing keys (private halves
3
- * sealed with the vault KEK, like credentials), each subject's revocation epoch, each
4
- * subject's turn bucket. Counting a subject's sessions by status uses the owner index of
5
- * migration 2; a second index on status would be written on every session transition.
6
- */
7
- export const subjectTokens = {
8
- version: 3,
9
- name: "subject_tokens",
10
- up: (s) => `
11
- CREATE TABLE ${s}.signing_keys (
12
- id text COLLATE "C" PRIMARY KEY,
13
- state text NOT NULL CHECK (state IN ('standby', 'current', 'previous', 'revoked')),
14
- alg text NOT NULL CHECK (alg = 'ES256'),
15
- public_jwk text NOT NULL,
16
- kek_id text NOT NULL,
17
- nonce bytea NOT NULL,
18
- ciphertext bytea NOT NULL,
19
- wrapped_dek bytea NOT NULL,
20
- created_at text NOT NULL,
21
- activated_at text,
22
- retired_at text,
23
- revoked_at text
24
- );
25
- CREATE UNIQUE INDEX signing_keys_one_standby ON ${s}.signing_keys (state) WHERE state = 'standby';
26
- CREATE UNIQUE INDEX signing_keys_one_current ON ${s}.signing_keys (state) WHERE state = 'current';
27
- CREATE UNIQUE INDEX signing_keys_one_previous ON ${s}.signing_keys (state) WHERE state = 'previous';
28
-
29
- CREATE TABLE ${s}.subject_epochs (
30
- subject text COLLATE "C" PRIMARY KEY,
31
- epoch bigint NOT NULL,
32
- revoked_at text NOT NULL
33
- );
34
-
35
- CREATE TABLE ${s}.subject_usage (
36
- subject text COLLATE "C" PRIMARY KEY,
37
- turn_tokens double precision NOT NULL,
38
- refilled_at text NOT NULL
39
- );
40
-
41
- `,
42
- };
@@ -1,6 +0,0 @@
1
- import type { Migration } from "./index.js";
2
- /**
3
- * Publishable keys (Host feature `browser-access`): public by design, so stored as they are,
4
- * with the origins a browser may use each from.
5
- */
6
- export declare const publishableKeys: Migration;
@@ -1,18 +0,0 @@
1
- /**
2
- * Publishable keys (Host feature `browser-access`): public by design, so stored as they are,
3
- * with the origins a browser may use each from.
4
- */
5
- export const publishableKeys = {
6
- version: 4,
7
- name: "publishable_keys",
8
- up: (s) => `
9
- CREATE TABLE ${s}.publishable_keys (
10
- id text COLLATE "C" PRIMARY KEY,
11
- key text COLLATE "C" NOT NULL UNIQUE,
12
- name text NOT NULL UNIQUE,
13
- origins_json text NOT NULL,
14
- created_at text NOT NULL,
15
- revoked_at text
16
- );
17
- `,
18
- };
@@ -1,6 +0,0 @@
1
- import type { Migration } from "./index.js";
2
- /**
3
- * Action endpoints: where the Runtime delivers each agent's Actions over HTTP, with the health
4
- * recent deliveries report, and the deadline of an Action being delivered.
5
- */
6
- export declare const actionEndpoints: Migration;
@@ -1,32 +0,0 @@
1
- /**
2
- * Action endpoints: where the Runtime delivers each agent's Actions over HTTP, with the health
3
- * recent deliveries report, and the deadline of an Action being delivered.
4
- */
5
- export const actionEndpoints = {
6
- version: 5,
7
- name: "action_endpoints",
8
- up: (s) => `
9
- CREATE TABLE ${s}.endpoints (
10
- agent_id text COLLATE "C" PRIMARY KEY,
11
- url text NOT NULL,
12
- implementation_version text NOT NULL,
13
- manifest_hash text,
14
- timeout_ms integer NOT NULL,
15
- max_concurrent integer NOT NULL,
16
- principal_id text,
17
- last_delivery_at text,
18
- last_success_at text,
19
- last_error_code text,
20
- last_error_message text,
21
- consecutive_failures integer NOT NULL DEFAULT 0,
22
- served_implementation_version text,
23
- served_manifest_hash text,
24
- created_at text NOT NULL,
25
- updated_at text NOT NULL
26
- );
27
-
28
- ALTER TABLE ${s}.actions
29
- ADD COLUMN deadline_at text GENERATED ALWAYS AS (${s}.doc(body)->>'deadlineAt') STORED;
30
- CREATE INDEX actions_deadline ON ${s}.actions (status, deadline_at);
31
- `,
32
- };
@@ -1,11 +0,0 @@
1
- import type { Migration } from "./index.js";
2
- /**
3
- * Protocol 3 removes executors: Actions are only delivered to Action endpoints.
4
- *
5
- * An Action an executor had claimed becomes `delivering` with a deadline that has already
6
- * passed, so the next sweep applies the delivery loss rule to it (`delivery.ts` `loseAction`):
7
- * a tool becomes `uncertain` with its `action.uncertain` event, and a hook, `fn` or `verify` is
8
- * delivered again. Open Actions lose the executor-only `claimId` and `leaseExpiresAt`; settled
9
- * ones are never delivered again and keep them.
10
- */
11
- export declare const dropExecutors: Migration;
@@ -1,32 +0,0 @@
1
- /**
2
- * Protocol 3 removes executors: Actions are only delivered to Action endpoints.
3
- *
4
- * An Action an executor had claimed becomes `delivering` with a deadline that has already
5
- * passed, so the next sweep applies the delivery loss rule to it (`delivery.ts` `loseAction`):
6
- * a tool becomes `uncertain` with its `action.uncertain` event, and a hook, `fn` or `verify` is
7
- * delivered again. Open Actions lose the executor-only `claimId` and `leaseExpiresAt`; settled
8
- * ones are never delivered again and keep them.
9
- */
10
- export const dropExecutors = {
11
- version: 6,
12
- name: "drop_executors",
13
- up: (s) => `
14
- DROP INDEX ${s}.actions_lease;
15
- ALTER TABLE ${s}.actions DROP COLUMN lease_expires_at;
16
-
17
- UPDATE ${s}.actions
18
- SET body = (
19
- ${s}.doc(body) - 'claimId' - 'leaseExpiresAt'
20
- || jsonb_build_object(
21
- 'status', 'delivering',
22
- 'deadlineAt', to_char(now() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')
23
- )
24
- )::json
25
- WHERE status = 'claimed';
26
- UPDATE ${s}.actions
27
- SET body = (${s}.doc(body) - 'claimId' - 'leaseExpiresAt')::json
28
- WHERE status IN ('pending', 'delivering');
29
-
30
- DROP TABLE ${s}.executors;
31
- `,
32
- };
@@ -1,7 +0,0 @@
1
- import type { Migration } from "./index.js";
2
- /**
3
- * Protocol 4 puts events on the `nylorun.event/2` envelope, where `createdAt` is `time`. The
4
- * outbox's `created_at` (its age, for relay lag) is generated from either, so rows written
5
- * before the upgrade keep theirs.
6
- */
7
- export declare const eventTime: Migration;
@@ -1,14 +0,0 @@
1
- /**
2
- * Protocol 4 puts events on the `nylorun.event/2` envelope, where `createdAt` is `time`. The
3
- * outbox's `created_at` (its age, for relay lag) is generated from either, so rows written
4
- * before the upgrade keep theirs.
5
- */
6
- export const eventTime = {
7
- version: 7,
8
- name: "event_time",
9
- up: (s) => `
10
- ALTER TABLE ${s}.outbox DROP COLUMN created_at;
11
- ALTER TABLE ${s}.outbox ADD COLUMN created_at text COLLATE "C"
12
- GENERATED ALWAYS AS (coalesce(${s}.doc(body)->>'time', ${s}.doc(body)->>'createdAt')) STORED;
13
- `,
14
- };
@@ -1,13 +0,0 @@
1
- import type { Migration } from "./index.js";
2
- /**
3
- * Durable Streams v1 (Durable Streams §18.1): session events move from the Tenant's outbox to
4
- * the shared record (`nylorun_streams`), and stream names lose their incarnation.
5
- *
6
- * **A fresh start for session data.** A Tenant that has sessions loses them, with their
7
- * commands, checkpoints, effects, Actions, links, outbox and turn buckets, as a
8
- * sessions-scope reset does; settings, agents, Action endpoints, keys, policy and vaults stay.
9
- * It moves to basin generation 1, and generation 0 (the basin holding the old streams) is
10
- * retired, so the Runtime deletes it when the Tenant opens. A Tenant without sessions stays at
11
- * generation 0: its basin holds no session stream it could collide with.
12
- */
13
- export declare const durableStreams: Migration;
@@ -1,35 +0,0 @@
1
- /**
2
- * Durable Streams v1 (Durable Streams §18.1): session events move from the Tenant's outbox to
3
- * the shared record (`nylorun_streams`), and stream names lose their incarnation.
4
- *
5
- * **A fresh start for session data.** A Tenant that has sessions loses them, with their
6
- * commands, checkpoints, effects, Actions, links, outbox and turn buckets, as a
7
- * sessions-scope reset does; settings, agents, Action endpoints, keys, policy and vaults stay.
8
- * It moves to basin generation 1, and generation 0 (the basin holding the old streams) is
9
- * retired, so the Runtime deletes it when the Tenant opens. A Tenant without sessions stays at
10
- * generation 0: its basin holds no session stream it could collide with.
11
- */
12
- export const durableStreams = {
13
- version: 8,
14
- name: "durable_streams",
15
- up: (s) => `
16
- ALTER TABLE ${s}.tenant
17
- ADD COLUMN basin_generation integer NOT NULL DEFAULT 0,
18
- ADD COLUMN retired_generations integer[] NOT NULL DEFAULT '{}';
19
- UPDATE ${s}.tenant SET basin_generation = 1, retired_generations = '{0}'
20
- WHERE EXISTS (SELECT 1 FROM ${s}.sessions);
21
-
22
- DELETE FROM ${s}.links;
23
- DELETE FROM ${s}.actions;
24
- DELETE FROM ${s}.effects;
25
- DELETE FROM ${s}.checkpoints;
26
- DELETE FROM ${s}.commands;
27
- DELETE FROM ${s}.sessions;
28
- DELETE FROM ${s}.subject_usage;
29
- DROP TABLE ${s}.outbox;
30
-
31
- ALTER TABLE ${s}.sessions
32
- DROP COLUMN stream_incarnation,
33
- DROP COLUMN next_event_seq;
34
- `,
35
- };
@@ -1,53 +0,0 @@
1
- /**
2
- * Forward-only, numbered migrations of one Tenant schema (architecture §14.6).
3
- *
4
- * Each schema records what it has applied in `<schema>.schema_version`, one
5
- * row per migration; its version is the highest row. Migrating runs every
6
- * missing step in order, in the caller's transaction, under a transaction-level
7
- * advisory lock on the schema so two processes never migrate the same schema
8
- * at once. A schema newer than the Runtime is never touched: migrating it
9
- * throws a `schema-too-new` quarantine and the Tenant is quarantined.
10
- *
11
- * Adding a migration: append `NNN_name.ts` with the next version to
12
- * `MIGRATIONS`. Never edit or reorder an applied migration.
13
- */
14
- import type { Sql, TransactionSql } from "postgres";
15
- export interface Migration {
16
- /** 1, 2, 3, … without gaps. */
17
- version: number;
18
- name: string;
19
- /** DDL for the quoted schema name `s` (for example `"tenant_tn_…"`). */
20
- up(s: string): string;
21
- }
22
- export declare const MIGRATIONS: readonly Migration[];
23
- /** The schema version this Runtime writes and expects. */
24
- export declare const POSTGRES_SCHEMA_VERSION: number;
25
- /** Checks that versions run 1, 2, 3, … Throws otherwise. */
26
- export declare function assertMigrations(migrations: readonly Migration[]): void;
27
- /**
28
- * Takes the schema's migration lock until the transaction ends. Waiting for it, and the
29
- * migrations or deletion done under it, may outlast the pool's statement timeout: it is lifted
30
- * for the transaction, since a migration that times out would quarantine the Tenant.
31
- */
32
- export declare function lockSchema(tx: TransactionSql, schema: string): Promise<void>;
33
- export declare function schemaExists(sql: Sql | TransactionSql, schema: string): Promise<boolean>;
34
- /**
35
- * The schema's version: 0 when it exists without a `schema_version` table,
36
- * undefined when the schema does not exist.
37
- */
38
- export declare function readSchemaVersion(sql: Sql | TransactionSql, schema: string): Promise<number | undefined>;
39
- /**
40
- * Creates the schema when missing and applies every missing migration, inside
41
- * `tx`. Call `lockSchema` first when other processes may migrate concurrently
42
- * (`migrateSchema` does). Throws a `schema-too-new` `QuarantineError` when the
43
- * schema is ahead of `migrations`.
44
- */
45
- export declare function migrateSchemaInTx(tx: TransactionSql, schema: string, migrations?: readonly Migration[]): Promise<{
46
- from: number;
47
- to: number;
48
- }>;
49
- /** `migrateSchemaInTx` in its own transaction, under the schema's migration lock. */
50
- export declare function migrateSchema(sql: Sql, schema: string, migrations?: readonly Migration[]): Promise<{
51
- from: number;
52
- to: number;
53
- }>;
@@ -1,96 +0,0 @@
1
- import { quarantine } from "../../../tenant/quarantine.js";
2
- import { quoteIdentifier, tenantIdFromSchema } from "../names.js";
3
- import { initial } from "./001_initial.js";
4
- import { sessionOwner } from "./002_session_owner.js";
5
- import { subjectTokens } from "./003_subject_tokens.js";
6
- import { publishableKeys } from "./004_publishable_keys.js";
7
- import { actionEndpoints } from "./005_action_endpoints.js";
8
- import { dropExecutors } from "./006_drop_executors.js";
9
- import { eventTime } from "./007_event_time.js";
10
- import { durableStreams } from "./008_durable_streams.js";
11
- export const MIGRATIONS = [
12
- initial,
13
- sessionOwner,
14
- subjectTokens,
15
- publishableKeys,
16
- actionEndpoints,
17
- dropExecutors,
18
- eventTime,
19
- durableStreams,
20
- ];
21
- /** The schema version this Runtime writes and expects. */
22
- export const POSTGRES_SCHEMA_VERSION = MIGRATIONS.at(-1).version;
23
- /** Checks that versions run 1, 2, 3, … Throws otherwise. */
24
- export function assertMigrations(migrations) {
25
- migrations.forEach((migration, index) => {
26
- if (migration.version !== index + 1)
27
- throw new Error(`Migration ${migration.name} has version ${migration.version}, expected ${index + 1}`);
28
- });
29
- }
30
- /**
31
- * Takes the schema's migration lock until the transaction ends. Waiting for it, and the
32
- * migrations or deletion done under it, may outlast the pool's statement timeout: it is lifted
33
- * for the transaction, since a migration that times out would quarantine the Tenant.
34
- */
35
- export async function lockSchema(tx, schema) {
36
- await tx `SET LOCAL statement_timeout = 0`;
37
- await tx `SELECT pg_advisory_xact_lock(hashtextextended(${`nylorun.schema:${schema}`}, 0))`;
38
- }
39
- export async function schemaExists(sql, schema) {
40
- const rows = await sql `SELECT 1 FROM pg_namespace WHERE nspname = ${schema}`;
41
- return rows.length > 0;
42
- }
43
- /**
44
- * The schema's version: 0 when it exists without a `schema_version` table,
45
- * undefined when the schema does not exist.
46
- */
47
- export async function readSchemaVersion(sql, schema) {
48
- const [row] = await sql `
49
- SELECT
50
- EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = ${schema}) AS has_schema,
51
- to_regclass(${`${quoteIdentifier(schema)}.schema_version`}) IS NOT NULL AS has_table`;
52
- if (!row.has_schema)
53
- return undefined;
54
- if (!row.has_table)
55
- return 0;
56
- const [version] = await sql `
57
- SELECT max(version)::int AS version FROM ${sql(`${schema}.schema_version`)}`;
58
- return version?.version ?? 0;
59
- }
60
- /**
61
- * Creates the schema when missing and applies every missing migration, inside
62
- * `tx`. Call `lockSchema` first when other processes may migrate concurrently
63
- * (`migrateSchema` does). Throws a `schema-too-new` `QuarantineError` when the
64
- * schema is ahead of `migrations`.
65
- */
66
- export async function migrateSchemaInTx(tx, schema, migrations = MIGRATIONS) {
67
- assertMigrations(migrations);
68
- const s = quoteIdentifier(schema);
69
- const latest = migrations.length;
70
- await tx.unsafe(`
71
- CREATE SCHEMA IF NOT EXISTS ${s};
72
- CREATE TABLE IF NOT EXISTS ${s}.schema_version (
73
- version integer PRIMARY KEY,
74
- name text NOT NULL,
75
- applied_at timestamptz NOT NULL DEFAULT now()
76
- );`);
77
- const from = (await readSchemaVersion(tx, schema)) ?? 0;
78
- if (from > latest)
79
- throw quarantine("schema-too-new", `Tenant schema version ${from} is newer than this Runtime's ${latest}`, { tenantId: tenantIdFromSchema(schema) ?? schema });
80
- for (const migration of migrations.slice(from)) {
81
- await tx.unsafe(migration.up(s));
82
- await tx `INSERT INTO ${tx(`${schema}.schema_version`)} (version, name)
83
- VALUES (${migration.version}, ${migration.name})`;
84
- }
85
- if (from < latest)
86
- await tx `UPDATE ${tx(`${schema}.tenant`)} SET schema_version = ${latest}`;
87
- return { from, to: latest };
88
- }
89
- /** `migrateSchemaInTx` in its own transaction, under the schema's migration lock. */
90
- export async function migrateSchema(sql, schema, migrations = MIGRATIONS) {
91
- const result = await sql.begin(async (tx) => {
92
- await lockSchema(tx, schema);
93
- return { result: await migrateSchemaInTx(tx, schema, migrations) };
94
- });
95
- return result.result;
96
- }