@nylorun/runtime 0.10.0-beta → 0.12.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 +86 -0
- package/README.md +53 -51
- package/dist/adapters/execution/restate.d.ts +130 -0
- package/dist/adapters/execution/restate.js +442 -0
- package/dist/adapters/sandbox/virtual.js +1 -1
- package/dist/adapters/streams/s2.d.ts +18 -0
- package/dist/adapters/streams/s2.js +361 -0
- package/dist/core/executors.d.ts +4 -1
- package/dist/core/executors.js +20 -1
- package/dist/core/flow-host.d.ts +93 -132
- package/dist/core/flow-host.js +282 -547
- package/dist/core/sandbox-routes.d.ts +13 -4
- package/dist/core/sandbox-routes.js +14 -12
- package/dist/execution/memory.d.ts +54 -0
- package/dist/execution/memory.js +217 -0
- package/dist/execution/types.d.ts +125 -0
- package/dist/execution/types.js +52 -0
- package/dist/host/config-for.d.ts +2 -1
- package/dist/host/config-for.js +3 -21
- package/dist/host/config.d.ts +0 -8
- package/dist/host/create-host.d.ts +36 -1
- package/dist/host/create-host.js +51 -24
- package/dist/host/execution.d.ts +61 -0
- package/dist/host/execution.js +69 -0
- package/dist/host/http.d.ts +4 -0
- package/dist/host/http.js +6 -0
- package/dist/host/index.d.ts +3 -1
- package/dist/host/index.js +2 -0
- package/dist/host/main.js +106 -47
- package/dist/host/stack-config.d.ts +72 -0
- package/dist/host/stack-config.js +193 -0
- package/dist/index.d.ts +1 -1
- package/dist/infra/database.d.ts +16 -0
- package/dist/infra/database.js +31 -0
- package/dist/infra/execution.d.ts +39 -0
- package/dist/infra/execution.js +68 -0
- package/dist/infra/index.d.ts +42 -0
- package/dist/infra/index.js +56 -0
- package/dist/infra/readiness.d.ts +33 -0
- package/dist/infra/readiness.js +53 -0
- package/dist/infra/streams.d.ts +17 -0
- package/dist/infra/streams.js +33 -0
- package/dist/infra/workers.d.ts +39 -0
- package/dist/infra/workers.js +31 -0
- package/dist/model/pi-model.d.ts +2 -2
- package/dist/model/pi-model.js +5 -5
- package/dist/sandbox/manager.d.ts +26 -8
- package/dist/sandbox/manager.js +95 -47
- package/dist/sandbox/select.d.ts +1 -1
- package/dist/sandbox/select.js +4 -5
- package/dist/sandbox/types.d.ts +2 -2
- package/dist/store/canonical.d.ts +5 -0
- package/dist/store/canonical.js +17 -0
- package/dist/store/cursor.d.ts +9 -0
- package/dist/store/cursor.js +18 -0
- package/dist/store/memory.d.ts +57 -0
- package/dist/store/memory.js +645 -0
- package/dist/store/ownership.d.ts +19 -0
- package/dist/store/ownership.js +33 -0
- package/dist/store/postgres/connect.d.ts +25 -0
- package/dist/store/postgres/connect.js +25 -0
- package/dist/store/postgres/locking.d.ts +16 -0
- package/dist/store/postgres/locking.js +22 -0
- package/dist/store/postgres/migrations/001_initial.d.ts +27 -0
- package/dist/store/postgres/migrations/001_initial.js +196 -0
- package/dist/store/postgres/migrations/002_session_owner.d.ts +6 -0
- package/dist/store/postgres/migrations/002_session_owner.js +13 -0
- package/dist/store/postgres/migrations/index.d.ts +49 -0
- package/dist/store/postgres/migrations/index.js +76 -0
- package/dist/store/postgres/names.d.ts +11 -0
- package/dist/store/postgres/names.js +42 -0
- package/dist/store/postgres/store.d.ts +11 -0
- package/dist/store/postgres/store.js +797 -0
- package/dist/store/postgres/tenants.d.ts +90 -0
- package/dist/store/postgres/tenants.js +214 -0
- package/dist/store/types.d.ts +442 -0
- package/dist/store/types.js +10 -0
- package/dist/streams/basin.d.ts +23 -0
- package/dist/streams/basin.js +51 -0
- package/dist/streams/memory.d.ts +25 -0
- package/dist/streams/memory.js +124 -0
- package/dist/streams/relay.d.ts +37 -0
- package/dist/streams/relay.js +254 -0
- package/dist/streams/types.d.ts +115 -0
- package/dist/streams/types.js +86 -0
- package/dist/tenant/actions.d.ts +153 -0
- package/dist/tenant/actions.js +191 -0
- package/dist/tenant/advance.d.ts +15 -0
- package/dist/tenant/advance.js +439 -0
- package/dist/tenant/auth.d.ts +32 -0
- package/dist/tenant/auth.js +169 -0
- package/dist/tenant/commands.d.ts +3 -0
- package/dist/tenant/commands.js +393 -0
- package/dist/tenant/context.d.ts +147 -0
- package/dist/tenant/context.js +48 -0
- package/dist/tenant/effects.d.ts +20 -0
- package/dist/tenant/effects.js +564 -0
- package/dist/tenant/envelope.d.ts +0 -3
- package/dist/tenant/envelope.js +2 -34
- package/dist/tenant/ephemeral.d.ts +15 -4
- package/dist/tenant/ephemeral.js +106 -38
- package/dist/tenant/http.d.ts +38 -0
- package/dist/tenant/http.js +53 -0
- package/dist/tenant/live.d.ts +92 -0
- package/dist/tenant/live.js +290 -0
- package/dist/tenant/model-setting.d.ts +16 -0
- package/dist/tenant/model-setting.js +12 -0
- package/dist/tenant/module.d.ts +29 -8
- package/dist/tenant/module.js +165 -158
- package/dist/tenant/paths.d.ts +12 -8
- package/dist/tenant/paths.js +38 -12
- package/dist/tenant/principals.d.ts +12 -13
- package/dist/tenant/principals.js +50 -38
- package/dist/tenant/quarantine-error.d.ts +1 -1
- package/dist/tenant/quarantine-error.js +2 -8
- package/dist/tenant/quarantine.d.ts +0 -8
- package/dist/tenant/quarantine.js +8 -30
- package/dist/tenant/reset.d.ts +7 -6
- package/dist/tenant/reset.js +7 -51
- package/dist/tenant/routes-tenant.d.ts +12 -0
- package/dist/tenant/routes-tenant.js +137 -0
- package/dist/tenant/routes.d.ts +9 -0
- package/dist/tenant/routes.js +151 -0
- package/dist/tenant/runtime.d.ts +59 -58
- package/dist/tenant/runtime.js +243 -2201
- package/dist/tenant/scheduler.d.ts +25 -0
- package/dist/tenant/scheduler.js +84 -0
- package/dist/tenant/session.d.ts +60 -0
- package/dist/tenant/session.js +94 -0
- package/dist/tenant/sessions.d.ts +40 -0
- package/dist/tenant/sessions.js +163 -0
- package/dist/tenant/status.d.ts +13 -4
- package/dist/tenant/status.js +76 -41
- package/dist/tenant/store-memory.d.ts +9 -12
- package/dist/tenant/store-memory.js +79 -68
- package/dist/tenant/store-pg.d.ts +15 -0
- package/dist/tenant/store-pg.js +140 -0
- package/dist/tenant/streams.d.ts +126 -0
- package/dist/tenant/streams.js +419 -0
- package/dist/tenant/sweep.d.ts +15 -0
- package/dist/tenant/sweep.js +122 -0
- package/dist/tenant/transcript.d.ts +104 -0
- package/dist/tenant/transcript.js +58 -0
- package/dist/tenant/types.d.ts +101 -15
- package/dist/tenant/types.js +23 -1
- package/dist/tenant/worker.d.ts +84 -0
- package/dist/tenant/worker.js +189 -0
- package/dist/vault/service.d.ts +44 -31
- package/dist/vault/service.js +454 -360
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +15 -14
- package/dist/adapters/sandbox/microsandbox.d.ts +0 -2
- package/dist/adapters/sandbox/microsandbox.js +0 -238
- package/dist/core/store.d.ts +0 -32
- package/dist/core/store.js +0 -143
- package/dist/launcher/commands.d.ts +0 -24
- package/dist/launcher/commands.js +0 -260
- package/dist/launcher/ensure-config.d.ts +0 -16
- package/dist/launcher/ensure-config.js +0 -79
- package/dist/launcher/errors.d.ts +0 -12
- package/dist/launcher/errors.js +0 -22
- package/dist/launcher/host-config.d.ts +0 -17
- package/dist/launcher/host-config.js +0 -64
- package/dist/launcher/host-state.d.ts +0 -17
- package/dist/launcher/host-state.js +0 -61
- package/dist/launcher/lifecycle.d.ts +0 -66
- package/dist/launcher/lifecycle.js +0 -407
- package/dist/launcher/locks.d.ts +0 -26
- package/dist/launcher/locks.js +0 -117
- package/dist/launcher/logs.d.ts +0 -18
- package/dist/launcher/logs.js +0 -117
- package/dist/launcher/main.d.ts +0 -2
- package/dist/launcher/main.js +0 -66
- package/dist/launcher/output.d.ts +0 -11
- package/dist/launcher/output.js +0 -68
- package/dist/launcher/paths.d.ts +0 -20
- package/dist/launcher/paths.js +0 -36
- package/dist/launcher/probe.d.ts +0 -23
- package/dist/launcher/probe.js +0 -72
- package/dist/launcher/protocol.d.ts +0 -62
- package/dist/launcher/protocol.js +0 -1
- package/dist/launcher/schema-guard.d.ts +0 -6
- package/dist/launcher/schema-guard.js +0 -36
- package/dist/launcher/spawn.d.ts +0 -22
- package/dist/launcher/spawn.js +0 -85
- package/dist/launcher/status.d.ts +0 -6
- package/dist/launcher/status.js +0 -65
- package/dist/tenant/migration.d.ts +0 -16
- package/dist/tenant/migration.js +0 -116
- package/dist/tenant/schema.d.ts +0 -23
- package/dist/tenant/schema.js +0 -151
- package/dist/tenant/store-fs.d.ts +0 -16
- package/dist/tenant/store-fs.js +0 -205
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** The model's tool call id and the harness invocation, for tool effects and tool actions. */
|
|
2
|
+
export function toolIds(context) {
|
|
3
|
+
const c = context;
|
|
4
|
+
return typeof c?.callId === "string" && typeof c.invocationId === "string"
|
|
5
|
+
? { callId: c.callId, invocationId: c.invocationId }
|
|
6
|
+
: {};
|
|
7
|
+
}
|
|
8
|
+
const agentOf = (request) => request.agent ? { agent: request.agent } : {};
|
|
9
|
+
/**
|
|
10
|
+
* `message.assistant` for a completed model effect: the step's text and tool calls. The
|
|
11
|
+
* provider returns a `ModelCandidate` or a bare string; anything else writes no event.
|
|
12
|
+
*/
|
|
13
|
+
export function assistantMessage(request, value) {
|
|
14
|
+
const invocationId = request.context
|
|
15
|
+
?.invocationId;
|
|
16
|
+
if (typeof invocationId !== "string")
|
|
17
|
+
return undefined;
|
|
18
|
+
const blocks = typeof value === "string"
|
|
19
|
+
? [{ type: "text", text: value }]
|
|
20
|
+
: Array.isArray(value?.output)
|
|
21
|
+
? value.output
|
|
22
|
+
: [];
|
|
23
|
+
let text = "";
|
|
24
|
+
const toolCalls = [];
|
|
25
|
+
for (const block of blocks) {
|
|
26
|
+
if (block?.type === "text" && typeof block.text === "string")
|
|
27
|
+
text += block.text;
|
|
28
|
+
else if (block?.type === "tool-call" &&
|
|
29
|
+
typeof block.id === "string" &&
|
|
30
|
+
typeof block.name === "string")
|
|
31
|
+
toolCalls.push({ callId: block.id, name: block.name, input: block.args });
|
|
32
|
+
}
|
|
33
|
+
if (!text && toolCalls.length === 0)
|
|
34
|
+
return undefined;
|
|
35
|
+
return { invocationId, text, toolCalls, ...agentOf(request) };
|
|
36
|
+
}
|
|
37
|
+
/** `tool.completed` for an MCP or sandbox tool: its output, or the tool error it reported. */
|
|
38
|
+
export function toolCompleted(request, value) {
|
|
39
|
+
const ids = toolIds(request.context);
|
|
40
|
+
if (!("callId" in ids))
|
|
41
|
+
return undefined;
|
|
42
|
+
const outcome = value;
|
|
43
|
+
const result = outcome?.kind === "failed"
|
|
44
|
+
? {
|
|
45
|
+
error: {
|
|
46
|
+
code: String(outcome.code ?? "tool.failed"),
|
|
47
|
+
message: String(outcome.message ?? ""),
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
: { output: outcome?.kind === "completed" ? outcome.output : value };
|
|
51
|
+
return {
|
|
52
|
+
...ids,
|
|
53
|
+
capabilityId: request.capabilityId,
|
|
54
|
+
toolName: request.toolName,
|
|
55
|
+
...result,
|
|
56
|
+
...agentOf(request),
|
|
57
|
+
};
|
|
58
|
+
}
|
package/dist/tenant/types.d.ts
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
2
|
import type { AdminTenant, AdminTenantStatus, HostAggregate, TenantEnvelope } from "@nylorun/core/contracts";
|
|
3
3
|
import type { FlowLimits } from "../core/limits.js";
|
|
4
|
+
import type { SessionStore } from "../store/types.js";
|
|
4
5
|
import type { SandboxBackend } from "../sandbox/types.js";
|
|
6
|
+
import type { TenantWorker } from "./worker.js";
|
|
5
7
|
export type TenantMode = "shared" | "ephemeral" | "test";
|
|
8
|
+
/**
|
|
9
|
+
* The Tenant directory on the Host root. The Tenant's data lives in its store (a Postgres
|
|
10
|
+
* schema); this holds what stays on the Host: the vault key, plugin data, logs, and the
|
|
11
|
+
* private home, tmp and sandbox directories.
|
|
12
|
+
*/
|
|
6
13
|
export interface TenantPaths {
|
|
7
14
|
root: string;
|
|
8
|
-
envelope: string;
|
|
9
|
-
database: string;
|
|
10
|
-
lock: string;
|
|
11
15
|
kek: string;
|
|
12
16
|
home: string;
|
|
13
17
|
tmp: string;
|
|
14
|
-
migration: string;
|
|
15
18
|
sandboxes: string;
|
|
16
19
|
pluginData: string;
|
|
17
20
|
logs: string;
|
|
@@ -34,12 +37,20 @@ export interface TenantConfig {
|
|
|
34
37
|
mode: TenantMode;
|
|
35
38
|
paths: TenantPaths;
|
|
36
39
|
sandbox: {
|
|
37
|
-
backend: "auto" | "
|
|
40
|
+
backend: "auto" | "virtual";
|
|
38
41
|
backends?: readonly SandboxBackend[];
|
|
39
42
|
};
|
|
40
43
|
model: TenantModelConfig;
|
|
41
44
|
childEnv: Readonly<Record<string, string>>;
|
|
45
|
+
/** Action claim lease. Default 30 s. */
|
|
42
46
|
leaseMs?: number;
|
|
47
|
+
/** Ownership lease of an advance (§10.6); renewed every third while it runs. Default 30 s. */
|
|
48
|
+
ownerLeaseMs?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Delay between Tenant sweep passes when the Tenant runs its own in-process execution.
|
|
51
|
+
* Default `min(leaseMs, 5 s)`. A Host-level execution sets its own.
|
|
52
|
+
*/
|
|
53
|
+
sweepIntervalMs?: number;
|
|
43
54
|
/** Operator flow limits (`RuntimeOptions.flow` / `workflows.md` §13). */
|
|
44
55
|
flow?: Partial<FlowLimits>;
|
|
45
56
|
/**
|
|
@@ -61,13 +72,19 @@ export interface TenantSummary {
|
|
|
61
72
|
connectedExecutors: number;
|
|
62
73
|
pendingActions: number;
|
|
63
74
|
uncertainEffects: number;
|
|
75
|
+
/** Events committed but not yet relayed to Durable Streams. */
|
|
76
|
+
outboxDepth?: number;
|
|
77
|
+
/** The oldest unrelayed event's age; 0 when none waits. */
|
|
78
|
+
relayLagMs?: number;
|
|
64
79
|
}
|
|
65
80
|
/** An open Tenant Runtime. Created only by the Tenant module. */
|
|
66
81
|
export interface TenantHandle {
|
|
67
82
|
readonly envelope: TenantEnvelope;
|
|
83
|
+
/** The handlers Durable Session Execution calls for this Tenant (`worker.ts`). */
|
|
84
|
+
readonly worker?: TenantWorker;
|
|
68
85
|
/** Headers already validated by the Host. Authenticates, authorizes, dispatches. */
|
|
69
86
|
handle(request: IncomingMessage, response: ServerResponse, url: URL): Promise<void>;
|
|
70
|
-
summary(): TenantSummary
|
|
87
|
+
summary(): Promise<TenantSummary>;
|
|
71
88
|
/** Stop scheduling; wait for or cancel active turns. */
|
|
72
89
|
drain(activeWork: "drain" | "cancel", timeoutMs?: number): Promise<void>;
|
|
73
90
|
close(): Promise<void>;
|
|
@@ -82,22 +99,43 @@ export type TenantResolution = {
|
|
|
82
99
|
quarantine: Quarantine;
|
|
83
100
|
};
|
|
84
101
|
export interface Quarantine {
|
|
85
|
-
code: "
|
|
102
|
+
code: "kek-missing" | "corrupt" | "schema-too-new" | "migration-failed" | "envelope-invalid" | "open-timeout" | "open-failed";
|
|
86
103
|
message: string;
|
|
87
104
|
repair: string;
|
|
88
|
-
lockPath?: string;
|
|
89
|
-
lockPid?: number;
|
|
90
105
|
}
|
|
91
106
|
export interface BootstrapPrincipal {
|
|
92
107
|
principalId: string;
|
|
93
108
|
credentialHash: string;
|
|
94
109
|
idempotencyKey: string;
|
|
110
|
+
/** When set, also registers application principal `studio` with this hash. */
|
|
111
|
+
studioCredentialHash?: string;
|
|
112
|
+
/** Application principals whose keys the admin key derives (feature `derived-principals`). */
|
|
113
|
+
derivedPrincipals?: readonly DerivedPrincipal[];
|
|
95
114
|
}
|
|
96
|
-
|
|
115
|
+
export interface DerivedPrincipal {
|
|
116
|
+
id: string;
|
|
117
|
+
credentialHash: string;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The deep module (§8). HTTP, CLI and tests use only this.
|
|
121
|
+
*
|
|
122
|
+
* Tenants open on demand (architecture §8.2): the first `resolve`, `status`, `worker` or
|
|
123
|
+
* `delete` naming a Tenant opens it (bounded by the open timeout) and caches the handle or
|
|
124
|
+
* the quarantine; `start` only marks discovery done, so a Host with many Tenants opens none
|
|
125
|
+
* at startup.
|
|
126
|
+
*/
|
|
97
127
|
export interface TenantModule {
|
|
128
|
+
/** Marks discovery done (`/ready`). Opens nothing. */
|
|
98
129
|
start(): Promise<void>;
|
|
99
130
|
readonly started: boolean;
|
|
100
|
-
|
|
131
|
+
/** Opens the Tenant on first use; a missing Tenant is `not-found`. */
|
|
132
|
+
resolve(id: string): Promise<TenantResolution>;
|
|
133
|
+
/**
|
|
134
|
+
* The Tenant's Worker handlers, opening it on demand, for `TenantWorkers.resolve`.
|
|
135
|
+
* Undefined when the Tenant does not exist, is quarantined or is being deleted, or the
|
|
136
|
+
* module is closed.
|
|
137
|
+
*/
|
|
138
|
+
worker(id: string): Promise<TenantWorker | undefined>;
|
|
101
139
|
create(input: {
|
|
102
140
|
tenantId: string;
|
|
103
141
|
name: string;
|
|
@@ -105,21 +143,69 @@ export interface TenantModule {
|
|
|
105
143
|
envelope: TenantEnvelope;
|
|
106
144
|
created: boolean;
|
|
107
145
|
}>;
|
|
146
|
+
/**
|
|
147
|
+
* Every Tenant the store holds, without opening any. A Tenant not opened yet is listed
|
|
148
|
+
* `open` when its envelope reads; opening it may still quarantine it.
|
|
149
|
+
*/
|
|
108
150
|
list(): Promise<readonly AdminTenant[]>;
|
|
109
151
|
status(id: string): Promise<AdminTenantStatus | undefined>;
|
|
110
152
|
delete(id: string, activeWork: "refuse" | "drain" | "cancel"): Promise<void>;
|
|
111
|
-
summarize(): HostAggregate
|
|
153
|
+
summarize(): Promise<HostAggregate>;
|
|
112
154
|
close(): Promise<void>;
|
|
113
155
|
}
|
|
114
|
-
/**
|
|
156
|
+
/**
|
|
157
|
+
* Storage adapter behind the module (§8): a Postgres schema per Tenant (`store-pg.ts`), and
|
|
158
|
+
* in-memory for tests (`store-memory.ts`).
|
|
159
|
+
*/
|
|
115
160
|
export interface TenantStore {
|
|
161
|
+
/** Ids of every Tenant the store holds. */
|
|
116
162
|
enumerate(): Promise<readonly string[]>;
|
|
163
|
+
/** Throws a quarantine error when unreadable, `TenantNotFoundError` when gone. */
|
|
117
164
|
readEnvelope(id: string): Promise<TenantEnvelope>;
|
|
165
|
+
/**
|
|
166
|
+
* Creates the Tenant, or returns `exists` when it already exists (whatever its bootstrap
|
|
167
|
+
* material; the module compares it with `bootstrapMatches`). The stored envelope's
|
|
168
|
+
* `schemaVersion` is the store's own; read it back with `readEnvelope`.
|
|
169
|
+
*/
|
|
118
170
|
create(envelope: TenantEnvelope, bootstrap: BootstrapPrincipal): Promise<"created" | "exists">;
|
|
119
171
|
bootstrapMatches(id: string, bootstrap: BootstrapPrincipal): Promise<boolean>;
|
|
172
|
+
/**
|
|
173
|
+
* Opens the Tenant Runtime; runs migration. Throws `TenantNotFoundError` when the Tenant
|
|
174
|
+
* does not exist, `TenantUnavailableError` when something outside the Tenant failed, and
|
|
175
|
+
* any other error (a quarantine error, ideally) when the Tenant itself cannot be opened.
|
|
176
|
+
*/
|
|
120
177
|
open(id: string): Promise<TenantHandle>;
|
|
178
|
+
/** Removes the Tenant: its data and its Tenant directory. */
|
|
121
179
|
trash(id: string, now: Date): Promise<void>;
|
|
180
|
+
/** Removes what a failed `create` left, never an existing Tenant. */
|
|
122
181
|
removePartial(id: string): Promise<void>;
|
|
123
182
|
}
|
|
124
|
-
/**
|
|
125
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Thrown by a store when a Tenant cannot be reached for a reason outside it (the database
|
|
185
|
+
* or Durable Session Execution is unavailable). The module does not quarantine it: the next
|
|
186
|
+
* use tries again. The Host answers 503.
|
|
187
|
+
*/
|
|
188
|
+
export declare class TenantUnavailableError extends Error {
|
|
189
|
+
readonly tenantId: string;
|
|
190
|
+
readonly status = 503;
|
|
191
|
+
constructor(tenantId: string, options?: {
|
|
192
|
+
cause?: unknown;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/** Thrown by `TenantStore.open` for a Tenant that does not exist. */
|
|
196
|
+
export declare class TenantNotFoundError extends Error {
|
|
197
|
+
readonly tenantId: string;
|
|
198
|
+
constructor(tenantId: string);
|
|
199
|
+
}
|
|
200
|
+
/** What a Tenant store hands the Tenant Runtime it opens. */
|
|
201
|
+
export interface OpenedTenant {
|
|
202
|
+
/**
|
|
203
|
+
* The Tenant's opened Session Store. The Tenant Runtime owns it from here on and closes it
|
|
204
|
+
* on close or on a failed open.
|
|
205
|
+
*/
|
|
206
|
+
store: SessionStore;
|
|
207
|
+
/** The Tenant envelope as its store reports it. */
|
|
208
|
+
envelope: TenantEnvelope;
|
|
209
|
+
}
|
|
210
|
+
/** Opens the Tenant Runtime on a store the Tenant store opened (injected, so tests can fake it). */
|
|
211
|
+
export type OpenTenantRuntime = (config: TenantConfig, opened: OpenedTenant) => Promise<TenantHandle>;
|
package/dist/tenant/types.js
CHANGED
|
@@ -1 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by a store when a Tenant cannot be reached for a reason outside it (the database
|
|
3
|
+
* or Durable Session Execution is unavailable). The module does not quarantine it: the next
|
|
4
|
+
* use tries again. The Host answers 503.
|
|
5
|
+
*/
|
|
6
|
+
export class TenantUnavailableError extends Error {
|
|
7
|
+
tenantId;
|
|
8
|
+
status = 503;
|
|
9
|
+
constructor(tenantId, options) {
|
|
10
|
+
super("Tenant is temporarily unavailable", options);
|
|
11
|
+
this.tenantId = tenantId;
|
|
12
|
+
this.name = "TenantUnavailableError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Thrown by `TenantStore.open` for a Tenant that does not exist. */
|
|
16
|
+
export class TenantNotFoundError extends Error {
|
|
17
|
+
tenantId;
|
|
18
|
+
constructor(tenantId) {
|
|
19
|
+
super(`Tenant ${tenantId} not found`);
|
|
20
|
+
this.tenantId = tenantId;
|
|
21
|
+
this.name = "TenantNotFoundError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { AdvanceResult, DurableExecution, StuckInvocation, WorkerHandlers } from "../execution/types.js";
|
|
2
|
+
import type { Logger } from "./types.js";
|
|
3
|
+
/** This process's Worker id: the `owner` it writes on the sessions it advances (§10.6). */
|
|
4
|
+
export declare const WORKER_ID: string;
|
|
5
|
+
/**
|
|
6
|
+
* Default advance deadline: 50 minutes, below the one-hour inactivity and abort timeouts the
|
|
7
|
+
* Restate adapter sets on the session object, so an advance always ends before Restate gives
|
|
8
|
+
* up on it.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_ADVANCE_DEADLINE_MS: number;
|
|
11
|
+
/** Default time an aborted advance has to settle before it is abandoned. */
|
|
12
|
+
export declare const DEFAULT_ADVANCE_GRACE_MS = 30000;
|
|
13
|
+
/** Why an advance's signal aborted (see "Abort reasons" above). */
|
|
14
|
+
export type AdvanceAbortKind = "cancel" | "shutdown" | "deadline" | "ownership.lost";
|
|
15
|
+
/** The abort reason of an advance. */
|
|
16
|
+
export declare class AdvanceAbort extends Error {
|
|
17
|
+
readonly kind: AdvanceAbortKind;
|
|
18
|
+
readonly name: string;
|
|
19
|
+
constructor(kind: AdvanceAbortKind, message: string, options?: {
|
|
20
|
+
cause?: unknown;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** The abort reason of an advance that ran past its deadline. */
|
|
24
|
+
export declare class AdvanceDeadlineError extends AdvanceAbort {
|
|
25
|
+
readonly deadlineMs: number;
|
|
26
|
+
readonly name = "AdvanceDeadlineError";
|
|
27
|
+
constructor(deadlineMs: number);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The kind of an aborted signal's reason, or `undefined` while it has not aborted. A reason
|
|
31
|
+
* that is not an `AdvanceAbort` came from outside the Tenant (the execution stopping) and
|
|
32
|
+
* counts as `shutdown`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function abortKind(signal: AbortSignal): AdvanceAbortKind | undefined;
|
|
35
|
+
/** One open Tenant's handlers. */
|
|
36
|
+
export interface TenantWorker {
|
|
37
|
+
/** Advances one session. Session outcomes never throw; only infrastructure errors do. */
|
|
38
|
+
advance(sessionId: string, signal: AbortSignal): Promise<AdvanceResult>;
|
|
39
|
+
/** One pass of the Tenant sweep. */
|
|
40
|
+
sweep(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
export interface TenantWorkersOptions {
|
|
43
|
+
/** Finds or opens a Tenant that is not registered on this process. */
|
|
44
|
+
resolve?: (tenantId: string) => Promise<TenantWorker | undefined>;
|
|
45
|
+
/** How long one advance may run before its signal aborts. Default `DEFAULT_ADVANCE_DEADLINE_MS`. */
|
|
46
|
+
advanceDeadlineMs?: number;
|
|
47
|
+
/**
|
|
48
|
+
* How long an advance whose signal aborted has to return before it is abandoned.
|
|
49
|
+
* Default `DEFAULT_ADVANCE_GRACE_MS`.
|
|
50
|
+
*/
|
|
51
|
+
advanceGraceMs?: number;
|
|
52
|
+
/** Receives a warning for each abandoned advance. */
|
|
53
|
+
logger?: Logger;
|
|
54
|
+
}
|
|
55
|
+
/** Registry of open Tenants' workers, dispatched to by `tenantId`. */
|
|
56
|
+
export declare class TenantWorkers {
|
|
57
|
+
private readonly options;
|
|
58
|
+
private readonly workers;
|
|
59
|
+
private readonly deadlineMs;
|
|
60
|
+
/**
|
|
61
|
+
* How long an aborted advance has to return before it is abandoned. Closing a Tenant waits
|
|
62
|
+
* as long for its advances before it abandons them (`scheduler.ts` `waitForIdle`).
|
|
63
|
+
*/
|
|
64
|
+
readonly graceMs: number;
|
|
65
|
+
constructor(options?: TenantWorkersOptions);
|
|
66
|
+
/** Registers an open Tenant's worker; the returned function unregisters exactly it. */
|
|
67
|
+
register(tenantId: string, worker: TenantWorker): () => void;
|
|
68
|
+
get(tenantId: string): TenantWorker | undefined;
|
|
69
|
+
private find;
|
|
70
|
+
/** The handlers to start a `DurableExecution` with. */
|
|
71
|
+
readonly handlers: WorkerHandlers;
|
|
72
|
+
/** Runs one advance under the deadline and the grace period (see the module comment). */
|
|
73
|
+
private bounded;
|
|
74
|
+
}
|
|
75
|
+
/** A Durable Session Execution together with the registry its handlers dispatch through. */
|
|
76
|
+
export interface TenantExecution {
|
|
77
|
+
readonly execution: DurableExecution;
|
|
78
|
+
readonly workers: TenantWorkers;
|
|
79
|
+
/**
|
|
80
|
+
* The Tenant's invocations that need an operator (paused or backing off), for Tenant
|
|
81
|
+
* status. Absent when the execution cannot report them (in-process execution).
|
|
82
|
+
*/
|
|
83
|
+
readonly stuckInvocations?: (tenantId: string) => Promise<StuckInvocation[]>;
|
|
84
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Worker side of Durable Session Execution (architecture §12.3): what a `DurableExecution`
|
|
3
|
+
* calls for one Tenant, and the registry that lets one execution serve every Tenant open on
|
|
4
|
+
* this process.
|
|
5
|
+
*
|
|
6
|
+
* - `TenantWorker` is one open Tenant's handlers: `advance(sessionId, signal)` (§10.5, in
|
|
7
|
+
* `advance.ts`) and `sweep()` (the Tenant sweep, in `sweep.ts`).
|
|
8
|
+
* - `TenantWorkers` is the registry. Its `handlers` are the `WorkerHandlers` an execution is
|
|
9
|
+
* started with; they dispatch by `tenantId` to the registered `TenantWorker`. A Tenant
|
|
10
|
+
* registers when it opens and unregisters when it closes. A call for a Tenant that is not
|
|
11
|
+
* open here asks the optional `resolve` hook (the Host can open it on demand); without one,
|
|
12
|
+
* the advance returns `done` and the sweep does nothing. Nothing is lost: the Tenant's sweep
|
|
13
|
+
* re-wakes its orphaned sessions once it is open again.
|
|
14
|
+
* - `TenantExecution` pairs an execution with its registry. The Host creates one per process
|
|
15
|
+
* (`host/execution.ts`) and passes it to every Tenant it opens; a Tenant opened without one
|
|
16
|
+
* (tests, ephemeral) gets its own in-process `MemoryExecution`.
|
|
17
|
+
*
|
|
18
|
+
* ## Advance deadline
|
|
19
|
+
*
|
|
20
|
+
* Restate's abort timeout does not interrupt a running handler (the advance's signal does not
|
|
21
|
+
* fire), so the registry bounds every advance itself:
|
|
22
|
+
*
|
|
23
|
+
* 1. At `advanceDeadlineMs` the advance's signal aborts with an `AdvanceDeadlineError`. The
|
|
24
|
+
* in-flight effect is aborted and the segment settles as a normal outcome (the effect and
|
|
25
|
+
* the turn become `uncertain`, or the turn fails with the deadline's message).
|
|
26
|
+
* 2. Once the signal has aborted, for whatever reason (deadline, Worker stop, Restate attempt
|
|
27
|
+
* end), the advance has `advanceGraceMs` to return. One that does not (an effect that
|
|
28
|
+
* ignores its signal) is abandoned: the handler returns `busy`, so the execution runs the
|
|
29
|
+
* session again. The abandoned advance has stopped renewing its lease (`advance.ts`), so
|
|
30
|
+
* the next advance takes over when the lease lapses (§11.4), and the epoch fences anything
|
|
31
|
+
* the abandoned one still tries to write.
|
|
32
|
+
*
|
|
33
|
+
* ## Abort reasons
|
|
34
|
+
*
|
|
35
|
+
* Every abort of an advance carries an `AdvanceAbort` whose `kind` says why, because the
|
|
36
|
+
* advance treats them differently (`advance.ts`, `effects.ts`):
|
|
37
|
+
*
|
|
38
|
+
* - `cancel`: a user cancel (or a reset) committed first. Results that arrive afterwards are
|
|
39
|
+
* discarded and the turn stays cancelled (§10.7).
|
|
40
|
+
* - `deadline`: the advance ran too long (`AdvanceDeadlineError`). The segment settles as a
|
|
41
|
+
* normal outcome.
|
|
42
|
+
* - `shutdown`: this Worker gives the advance up (Worker stop, Tenant close, the Restate
|
|
43
|
+
* attempt ended). Nothing about the turn is settled: outcomes already in hand are recorded,
|
|
44
|
+
* ownership is released and the advance returns `busy`, so the next advance, here or on
|
|
45
|
+
* another Worker, resumes the segment from its checkpoint with the cached outcomes.
|
|
46
|
+
* - `ownership.lost`: another advance took the session over; this one writes nothing more.
|
|
47
|
+
*
|
|
48
|
+
* An abort that arrives through the execution's signal is a `shutdown`, whatever its reason.
|
|
49
|
+
*/
|
|
50
|
+
import { hostname } from "node:os";
|
|
51
|
+
import { randomBytes } from "node:crypto";
|
|
52
|
+
/** This process's Worker id: the `owner` it writes on the sessions it advances (§10.6). */
|
|
53
|
+
export const WORKER_ID = `worker-${hostname()}-${process.pid}-${randomBytes(4).toString("hex")}`;
|
|
54
|
+
/**
|
|
55
|
+
* Default advance deadline: 50 minutes, below the one-hour inactivity and abort timeouts the
|
|
56
|
+
* Restate adapter sets on the session object, so an advance always ends before Restate gives
|
|
57
|
+
* up on it.
|
|
58
|
+
*/
|
|
59
|
+
export const DEFAULT_ADVANCE_DEADLINE_MS = 50 * 60_000;
|
|
60
|
+
/** Default time an aborted advance has to settle before it is abandoned. */
|
|
61
|
+
export const DEFAULT_ADVANCE_GRACE_MS = 30_000;
|
|
62
|
+
/** The abort reason of an advance. */
|
|
63
|
+
export class AdvanceAbort extends Error {
|
|
64
|
+
kind;
|
|
65
|
+
name = "AdvanceAbort";
|
|
66
|
+
constructor(kind, message, options) {
|
|
67
|
+
super(message, options);
|
|
68
|
+
this.kind = kind;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** The abort reason of an advance that ran past its deadline. */
|
|
72
|
+
export class AdvanceDeadlineError extends AdvanceAbort {
|
|
73
|
+
deadlineMs;
|
|
74
|
+
name = "AdvanceDeadlineError";
|
|
75
|
+
constructor(deadlineMs) {
|
|
76
|
+
super("deadline", `The advance ran past its ${deadlineMs} ms deadline`);
|
|
77
|
+
this.deadlineMs = deadlineMs;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The kind of an aborted signal's reason, or `undefined` while it has not aborted. A reason
|
|
82
|
+
* that is not an `AdvanceAbort` came from outside the Tenant (the execution stopping) and
|
|
83
|
+
* counts as `shutdown`.
|
|
84
|
+
*/
|
|
85
|
+
export function abortKind(signal) {
|
|
86
|
+
if (!signal.aborted)
|
|
87
|
+
return undefined;
|
|
88
|
+
return signal.reason instanceof AdvanceAbort ? signal.reason.kind : "shutdown";
|
|
89
|
+
}
|
|
90
|
+
/** The execution's abort reason as a `shutdown`, keeping its message. */
|
|
91
|
+
function shutdownOf(reason) {
|
|
92
|
+
if (reason instanceof AdvanceAbort)
|
|
93
|
+
return reason;
|
|
94
|
+
return new AdvanceAbort("shutdown", reason instanceof Error ? reason.message : "The Worker stopped the advance", { cause: reason });
|
|
95
|
+
}
|
|
96
|
+
const DONE = { status: "done" };
|
|
97
|
+
/** Registry of open Tenants' workers, dispatched to by `tenantId`. */
|
|
98
|
+
export class TenantWorkers {
|
|
99
|
+
options;
|
|
100
|
+
workers = new Map();
|
|
101
|
+
deadlineMs;
|
|
102
|
+
/**
|
|
103
|
+
* How long an aborted advance has to return before it is abandoned. Closing a Tenant waits
|
|
104
|
+
* as long for its advances before it abandons them (`scheduler.ts` `waitForIdle`).
|
|
105
|
+
*/
|
|
106
|
+
graceMs;
|
|
107
|
+
constructor(options = {}) {
|
|
108
|
+
this.options = options;
|
|
109
|
+
this.deadlineMs = positive("advanceDeadlineMs", options.advanceDeadlineMs ?? DEFAULT_ADVANCE_DEADLINE_MS);
|
|
110
|
+
this.graceMs = positive("advanceGraceMs", options.advanceGraceMs ?? DEFAULT_ADVANCE_GRACE_MS);
|
|
111
|
+
}
|
|
112
|
+
/** Registers an open Tenant's worker; the returned function unregisters exactly it. */
|
|
113
|
+
register(tenantId, worker) {
|
|
114
|
+
this.workers.set(tenantId, worker);
|
|
115
|
+
return () => {
|
|
116
|
+
if (this.workers.get(tenantId) === worker)
|
|
117
|
+
this.workers.delete(tenantId);
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
get(tenantId) {
|
|
121
|
+
return this.workers.get(tenantId);
|
|
122
|
+
}
|
|
123
|
+
async find(tenantId) {
|
|
124
|
+
return this.workers.get(tenantId) ?? (await this.options.resolve?.(tenantId));
|
|
125
|
+
}
|
|
126
|
+
/** The handlers to start a `DurableExecution` with. */
|
|
127
|
+
handlers = {
|
|
128
|
+
advance: async (tenantId, sessionId, signal) => {
|
|
129
|
+
const worker = await this.find(tenantId);
|
|
130
|
+
return worker ? this.bounded(tenantId, sessionId, worker, signal) : DONE;
|
|
131
|
+
},
|
|
132
|
+
sweep: async (tenantId) => {
|
|
133
|
+
await (await this.find(tenantId))?.sweep();
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
/** Runs one advance under the deadline and the grace period (see the module comment). */
|
|
137
|
+
async bounded(tenantId, sessionId, worker, signal) {
|
|
138
|
+
const controller = new AbortController();
|
|
139
|
+
const abort = (reason) => {
|
|
140
|
+
if (!controller.signal.aborted)
|
|
141
|
+
controller.abort(reason);
|
|
142
|
+
};
|
|
143
|
+
const forward = () => abort(shutdownOf(signal.reason));
|
|
144
|
+
if (signal.aborted)
|
|
145
|
+
forward();
|
|
146
|
+
else
|
|
147
|
+
signal.addEventListener("abort", forward, { once: true });
|
|
148
|
+
const deadline = setTimeout(() => abort(new AdvanceDeadlineError(this.deadlineMs)), this.deadlineMs);
|
|
149
|
+
let grace;
|
|
150
|
+
let armGrace;
|
|
151
|
+
const abandoned = new Promise((resolve) => {
|
|
152
|
+
armGrace = () => {
|
|
153
|
+
grace = setTimeout(() => {
|
|
154
|
+
this.options.logger?.warn("advance abandoned after abort", {
|
|
155
|
+
tenantId,
|
|
156
|
+
sessionId,
|
|
157
|
+
graceMs: this.graceMs,
|
|
158
|
+
reason: controller.signal.reason instanceof Error
|
|
159
|
+
? controller.signal.reason.message
|
|
160
|
+
: String(controller.signal.reason),
|
|
161
|
+
});
|
|
162
|
+
resolve({ status: "busy", retryAfterMs: 0 });
|
|
163
|
+
}, this.graceMs);
|
|
164
|
+
};
|
|
165
|
+
if (controller.signal.aborted)
|
|
166
|
+
armGrace();
|
|
167
|
+
else
|
|
168
|
+
controller.signal.addEventListener("abort", armGrace, { once: true });
|
|
169
|
+
});
|
|
170
|
+
try {
|
|
171
|
+
// `race` keeps handling the advance's outcome after it is abandoned.
|
|
172
|
+
return await Promise.race([worker.advance(sessionId, controller.signal), abandoned]);
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
clearTimeout(deadline);
|
|
176
|
+
clearTimeout(grace);
|
|
177
|
+
signal.removeEventListener("abort", forward);
|
|
178
|
+
if (armGrace)
|
|
179
|
+
controller.signal.removeEventListener("abort", armGrace);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/** The longest delay `setTimeout` keeps (about 24.8 days). */
|
|
184
|
+
const MAX_TIMEOUT_MS = 2 ** 31 - 1;
|
|
185
|
+
function positive(name, value) {
|
|
186
|
+
if (!Number.isFinite(value) || value <= 0 || value > MAX_TIMEOUT_MS)
|
|
187
|
+
throw new Error(`${name} must be positive and at most ${MAX_TIMEOUT_MS}`);
|
|
188
|
+
return value;
|
|
189
|
+
}
|
package/dist/vault/service.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { DatabaseSync } from "node:sqlite";
|
|
2
1
|
import type { CreateCredentialRequest, CreateVaultRequest, CredentialInfo, CredentialSelection, HostModelProviderInfo, HostModelView, PutHostModelRequest, RotateCredentialRequest, SelectHostModelRequest, VaultInfo } from "@nylorun/core/contracts";
|
|
2
|
+
import type { SessionStore, Tx } from "../store/types.js";
|
|
3
3
|
export type HostModelSecret = {
|
|
4
4
|
provider: string;
|
|
5
5
|
model: string;
|
|
@@ -31,27 +31,42 @@ export type AuthorizeResult = {
|
|
|
31
31
|
credentialIds: string[];
|
|
32
32
|
reason: string;
|
|
33
33
|
};
|
|
34
|
+
export interface VaultServiceOptions {
|
|
35
|
+
store: SessionStore;
|
|
36
|
+
/** The Tenant key-encryption key. May read or create the key file. */
|
|
37
|
+
kek: () => Buffer;
|
|
38
|
+
/** Used only for OAuth refresh, always outside a transaction. */
|
|
39
|
+
fetch: typeof fetch;
|
|
40
|
+
}
|
|
34
41
|
export declare class VaultService {
|
|
35
|
-
private readonly
|
|
36
|
-
private readonly tx;
|
|
42
|
+
private readonly store;
|
|
37
43
|
private readonly kek;
|
|
38
44
|
private readonly fetchImpl;
|
|
39
|
-
constructor(
|
|
40
|
-
createVault(body: CreateVaultRequest): VaultInfo
|
|
41
|
-
listVaults(ownerUserId: string): VaultInfo[]
|
|
42
|
-
getVault(id: string): VaultInfo
|
|
43
|
-
|
|
45
|
+
constructor(options: VaultServiceOptions);
|
|
46
|
+
createVault(body: CreateVaultRequest): Promise<VaultInfo>;
|
|
47
|
+
listVaults(ownerUserId: string): Promise<VaultInfo[]>;
|
|
48
|
+
getVault(id: string): Promise<VaultInfo>;
|
|
49
|
+
/** Another owner's vault, or the host vault, is the same 404 as a missing one. */
|
|
50
|
+
assertOwner(id: string, ownerUserId: string): Promise<void>;
|
|
51
|
+
deleteVault(id: string): Promise<{
|
|
44
52
|
id: string;
|
|
45
|
-
}
|
|
46
|
-
createCredential(vaultId: string, body: CreateCredentialRequest): CredentialInfo
|
|
47
|
-
listCredentials(vaultId: string): CredentialInfo[]
|
|
48
|
-
getCredential(vaultId: string, id: string): CredentialInfo
|
|
49
|
-
rotateCredential(vaultId: string, id: string, body: RotateCredentialRequest): CredentialInfo
|
|
50
|
-
deleteCredential(vaultId: string, id: string): {
|
|
53
|
+
}>;
|
|
54
|
+
createCredential(vaultId: string, body: CreateCredentialRequest): Promise<CredentialInfo>;
|
|
55
|
+
listCredentials(vaultId: string): Promise<CredentialInfo[]>;
|
|
56
|
+
getCredential(vaultId: string, id: string): Promise<CredentialInfo>;
|
|
57
|
+
rotateCredential(vaultId: string, id: string, body: RotateCredentialRequest): Promise<CredentialInfo>;
|
|
58
|
+
deleteCredential(vaultId: string, id: string): Promise<{
|
|
51
59
|
id: string;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
}>;
|
|
61
|
+
/**
|
|
62
|
+
* Checks a session's vaults and selections. Run in the session PUT transaction. `opaque`
|
|
63
|
+
* (a request acting for a subject) reports another owner's vault as the 404 of a missing one.
|
|
64
|
+
*/
|
|
65
|
+
assertAttachment(t: Tx, ownerUserId: string, vaultIds: readonly string[], selections: readonly CredentialSelection[], options?: {
|
|
66
|
+
opaque?: boolean;
|
|
67
|
+
}): Promise<void>;
|
|
68
|
+
/** Writes the `attach` audit row. Run in the session PUT transaction. */
|
|
69
|
+
recordAttachment(t: Tx, sessionId: string, vaultIds: readonly string[]): Promise<void>;
|
|
55
70
|
authorize(input: {
|
|
56
71
|
sessionId: string;
|
|
57
72
|
vaultIds: readonly string[];
|
|
@@ -59,13 +74,14 @@ export declare class VaultService {
|
|
|
59
74
|
url: string;
|
|
60
75
|
serverName?: string;
|
|
61
76
|
}): Promise<AuthorizeResult>;
|
|
62
|
-
getHostModel(): HostModelView
|
|
63
|
-
listHostProviders(): {
|
|
77
|
+
getHostModel(): Promise<HostModelView>;
|
|
78
|
+
listHostProviders(): Promise<{
|
|
64
79
|
providers: HostModelProviderInfo[];
|
|
65
|
-
}
|
|
66
|
-
putHostModel(body: PutHostModelRequest): HostModelView
|
|
67
|
-
selectHostModel(body: SelectHostModelRequest): HostModelView
|
|
68
|
-
|
|
80
|
+
}>;
|
|
81
|
+
putHostModel(body: PutHostModelRequest): Promise<HostModelView>;
|
|
82
|
+
selectHostModel(body: SelectHostModelRequest): Promise<HostModelView>;
|
|
83
|
+
/** Reads the active host model secret. Decrypts after the read commits. */
|
|
84
|
+
readHostModel(): Promise<HostModelSecret | undefined>;
|
|
69
85
|
updateHostCredential(credential: {
|
|
70
86
|
type: "api_key" | "oauth";
|
|
71
87
|
key?: string;
|
|
@@ -73,27 +89,24 @@ export declare class VaultService {
|
|
|
73
89
|
refresh?: string;
|
|
74
90
|
access?: string;
|
|
75
91
|
expires?: number;
|
|
76
|
-
}): void
|
|
77
|
-
reject(route: string): void
|
|
92
|
+
}): Promise<void>;
|
|
93
|
+
reject(route: string): Promise<void>;
|
|
94
|
+
/** Calls the token endpoint outside any transaction, then stores the result. */
|
|
78
95
|
private refresh;
|
|
79
96
|
private replay;
|
|
80
|
-
|
|
97
|
+
/** Re-seals a user credential's payload and returns the updated row. */
|
|
81
98
|
private writePayload;
|
|
82
|
-
private readPayload;
|
|
83
99
|
private vaultInfo;
|
|
84
|
-
private vaultRow;
|
|
85
100
|
private ensureHostVault;
|
|
86
101
|
private validateHostModel;
|
|
87
102
|
private insertHostCredential;
|
|
88
|
-
private
|
|
103
|
+
private hostModelView;
|
|
89
104
|
private hostModelRows;
|
|
90
105
|
private hostCredentialRowFor;
|
|
91
106
|
private activeHostCredentialRow;
|
|
92
107
|
private activeProviderId;
|
|
93
108
|
private setActiveProvider;
|
|
94
109
|
private deleteHostProviderRows;
|
|
95
|
-
private credentialInfo;
|
|
96
110
|
private credentialRow;
|
|
97
|
-
private rowsForVault;
|
|
98
111
|
private audit;
|
|
99
112
|
}
|