witnora 0.13.4 → 0.13.6
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/dist/cli.js +2 -2
- package/dist/gateway.js +506 -39
- package/dist/internal/control-client/collector-gateway.d.ts +9 -1
- package/dist/internal/control-client/collector-gateway.d.ts.map +1 -1
- package/dist/internal/control-client/collector-gateway.js +28 -3
- package/dist/internal/control-client/remote-collector.d.ts +20 -0
- package/dist/internal/control-client/remote-collector.d.ts.map +1 -1
- package/dist/internal/control-client/remote-collector.js +1 -0
- package/dist/onboard.js +99 -12
- package/dist/runtime-bootstrap.js +333 -0
- package/dist/runtime-sandbox-fixture.js +166 -0
- package/dist/runtime-sandbox-kit.js +295 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CustomerSourceKeyRing, type CustomerSourceSigner, type RemoteCollectorAck, type RemoteTrustedSourceRecord } from "./remote-collector.js";
|
|
1
|
+
import { CustomerSourceKeyRing, type CustomerSourceSigner, type CollectorRuntimeHeartbeat, type RuntimeReadinessBinding, type RemoteCollectorAck, type RemoteTrustedSourceRecord } from "./remote-collector.js";
|
|
2
2
|
export interface RemoteCollectorTransport {
|
|
3
3
|
registerSourceKey(input: {
|
|
4
4
|
collectorId: string;
|
|
@@ -12,6 +12,7 @@ export interface RemoteCollectorTransport {
|
|
|
12
12
|
signer: CustomerSourceSigner;
|
|
13
13
|
pendingRecordCount: number;
|
|
14
14
|
lastAckSequence?: number;
|
|
15
|
+
runtime?: CollectorRuntimeHeartbeat;
|
|
15
16
|
}): Promise<Record<string, unknown>>;
|
|
16
17
|
reconcile(runId: string, receipt: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
17
18
|
proposeAction(proposal: Record<string, unknown>, idempotencyKey: string): Promise<Record<string, unknown>>;
|
|
@@ -37,7 +38,14 @@ export interface CustomerOwnedCollectorGatewayOptions {
|
|
|
37
38
|
}): Promise<unknown>;
|
|
38
39
|
status(): Promise<Record<string, unknown>>;
|
|
39
40
|
close?(): void | Promise<void>;
|
|
41
|
+
runtimeBinding?: {
|
|
42
|
+
classification: "LOCAL_SANDBOX_ONLY";
|
|
43
|
+
binding: RuntimeReadinessBinding;
|
|
44
|
+
fixtureReady: boolean;
|
|
45
|
+
workerReady?: boolean;
|
|
46
|
+
};
|
|
40
47
|
};
|
|
48
|
+
runtimeBinding?: RuntimeReadinessBinding;
|
|
41
49
|
}
|
|
42
50
|
export interface CustomerOwnedCollectorGateway {
|
|
43
51
|
baseUrl: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector-gateway.d.ts","sourceRoot":"","sources":["../../../../agentcert-sdk/src/collector-gateway.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,qBAAqB,EAGrB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC/B,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,wBAAwB;IACvC,iBAAiB,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACjJ,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAClH,SAAS,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"collector-gateway.d.ts","sourceRoot":"","sources":["../../../../agentcert-sdk/src/collector-gateway.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,qBAAqB,EAGrB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC/B,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,wBAAwB;IACvC,iBAAiB,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACjJ,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAClH,SAAS,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,yBAAyB,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrM,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7F,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3G,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9D,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACjI;AAED,MAAM,WAAW,oCAAoC;IACnD,MAAM,EAAE,wBAAwB,CAAC;IACjC,OAAO,EAAE,qBAAqB,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE;QACb,KAAK,CAAC,KAAK,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACxF,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,cAAc,CAAC,EAAE;YAAE,cAAc,EAAE,oBAAoB,CAAC;YAAC,OAAO,EAAE,uBAAuB,CAAC;YAAC,YAAY,EAAE,OAAO,CAAC;YAAC,WAAW,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;KAC3I,CAAC;IACF,cAAc,CAAC,EAAE,uBAAuB,CAAC;CAC1C;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,KAAK,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7E,MAAM,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,kDAAkD,CAAC;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AAUD,wBAAsB,kCAAkC,CAAC,OAAO,EAAE,oCAAoC,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAmM9I"}
|
|
@@ -10,6 +10,10 @@ export async function startCustomerOwnedCollectorGateway(options) {
|
|
|
10
10
|
const storageDirectory = resolve(options.storageDirectory);
|
|
11
11
|
await mkdir(storageDirectory, { recursive: true });
|
|
12
12
|
const signer = options.keyRing.activeSigner();
|
|
13
|
+
const runtimeBinding = options.actionWorker?.runtimeBinding?.binding ?? options.runtimeBinding;
|
|
14
|
+
if (runtimeBinding && (runtimeBinding.collectorId !== options.keyRing.collectorId || runtimeBinding.sourceKeyId !== signer.keyId)) {
|
|
15
|
+
throw new Error("runtimeBinding must match the Gateway collector and active source key.");
|
|
16
|
+
}
|
|
13
17
|
let sourceKeyRegistered = false;
|
|
14
18
|
const journals = new Map();
|
|
15
19
|
const activeCollector = {
|
|
@@ -98,7 +102,8 @@ export async function startCustomerOwnedCollectorGateway(options) {
|
|
|
98
102
|
if (request.method === "POST" && url.pathname === "/v1/actions") {
|
|
99
103
|
const body = await readJson(request, options.maxBodyBytes ?? 1_048_576);
|
|
100
104
|
const proposal = object(body.proposal);
|
|
101
|
-
const
|
|
105
|
+
const hostedProposal = runtimeBinding ? { ...proposal, localRuntimeBinding: runtimeBinding } : proposal;
|
|
106
|
+
const action = await options.client.proposeAction(hostedProposal, identifier(body.idempotencyKey, "idempotencyKey"));
|
|
102
107
|
if (options.actionWorker)
|
|
103
108
|
await options.actionWorker.track({ actionId: identifier(action.id, "actionId"), proposal });
|
|
104
109
|
return json(response, 202, action);
|
|
@@ -165,15 +170,17 @@ export async function startCustomerOwnedCollectorGateway(options) {
|
|
|
165
170
|
if (!address || typeof address === "string")
|
|
166
171
|
throw new Error("Collector gateway did not bind a TCP port.");
|
|
167
172
|
const flushTimer = setInterval(() => void flush(), options.flushIntervalMs ?? 5_000);
|
|
168
|
-
const
|
|
173
|
+
const sendHeartbeat = async () => {
|
|
169
174
|
const current = await status();
|
|
170
175
|
try {
|
|
171
176
|
await ensureSourceKeyRegistered();
|
|
177
|
+
const workerStatus = options.actionWorker ? await options.actionWorker.status() : undefined;
|
|
172
178
|
await options.client.heartbeat({
|
|
173
179
|
collectorId: activeCollector.id,
|
|
174
180
|
signer,
|
|
175
181
|
pendingRecordCount: current.pendingRecordCount,
|
|
176
182
|
lastAckSequence: current.lastAckSequence,
|
|
183
|
+
runtime: runtimeBinding && workerStatus ? runtimeHeartbeat(runtimeBinding, workerStatus, options.actionWorker?.runtimeBinding?.fixtureReady) : undefined,
|
|
177
184
|
});
|
|
178
185
|
lastRemoteSuccessAt = new Date().toISOString();
|
|
179
186
|
lastRemoteError = undefined;
|
|
@@ -181,12 +188,14 @@ export async function startCustomerOwnedCollectorGateway(options) {
|
|
|
181
188
|
catch (error) {
|
|
182
189
|
lastRemoteError = message(error);
|
|
183
190
|
}
|
|
184
|
-
}
|
|
191
|
+
};
|
|
192
|
+
const heartbeatTimer = setInterval(() => void sendHeartbeat(), options.heartbeatIntervalMs ?? 30_000);
|
|
185
193
|
flushTimer.unref();
|
|
186
194
|
heartbeatTimer.unref();
|
|
187
195
|
for (const runId of await discoverRunIds(storageDirectory))
|
|
188
196
|
await journalFor(runId);
|
|
189
197
|
await flush();
|
|
198
|
+
await sendHeartbeat();
|
|
190
199
|
return {
|
|
191
200
|
baseUrl: `http://${options.host ?? "127.0.0.1"}:${address.port}`,
|
|
192
201
|
close: async () => {
|
|
@@ -200,6 +209,22 @@ export async function startCustomerOwnedCollectorGateway(options) {
|
|
|
200
209
|
status,
|
|
201
210
|
};
|
|
202
211
|
}
|
|
212
|
+
function runtimeHeartbeat(binding, status, configuredFixtureReady) {
|
|
213
|
+
const boundary = status.runtimeBoundary && typeof status.runtimeBoundary === "object" && !Array.isArray(status.runtimeBoundary)
|
|
214
|
+
? status.runtimeBoundary
|
|
215
|
+
: undefined;
|
|
216
|
+
const fixture = boundary?.fixture && typeof boundary.fixture === "object" && !Array.isArray(boundary.fixture)
|
|
217
|
+
? boundary.fixture
|
|
218
|
+
: undefined;
|
|
219
|
+
const lastError = typeof status.lastError === "string" && status.lastError.trim() ? status.lastError.slice(0, 1_000) : undefined;
|
|
220
|
+
return {
|
|
221
|
+
classification: "LOCAL_SANDBOX_ONLY",
|
|
222
|
+
binding,
|
|
223
|
+
workerReady: status.ready === true,
|
|
224
|
+
fixtureReady: fixture?.ready === true || status.fixtureReady === true || configuredFixtureReady === true,
|
|
225
|
+
...(lastError ? { lastError } : {}),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
203
228
|
class GatewayRunJournal {
|
|
204
229
|
runId;
|
|
205
230
|
collector;
|
|
@@ -38,6 +38,25 @@ export interface RemoteCollectorAck {
|
|
|
38
38
|
alerts: Array<Record<string, unknown>>;
|
|
39
39
|
run: Record<string, unknown>;
|
|
40
40
|
}
|
|
41
|
+
export interface RuntimeReadinessBinding {
|
|
42
|
+
collectorId: string;
|
|
43
|
+
sourceKeyId: string;
|
|
44
|
+
configDigestSha256: string;
|
|
45
|
+
runtimeIdentity: {
|
|
46
|
+
id: string;
|
|
47
|
+
};
|
|
48
|
+
mandateDigestSha256: string;
|
|
49
|
+
adapterDigestSha256: string;
|
|
50
|
+
probeDigestSha256: string;
|
|
51
|
+
fixtureContractDigestSha256: string;
|
|
52
|
+
}
|
|
53
|
+
export interface CollectorRuntimeHeartbeat {
|
|
54
|
+
classification: "LOCAL_SANDBOX_ONLY";
|
|
55
|
+
binding: RuntimeReadinessBinding;
|
|
56
|
+
workerReady: boolean;
|
|
57
|
+
fixtureReady: boolean;
|
|
58
|
+
lastError?: string;
|
|
59
|
+
}
|
|
41
60
|
export interface RemoteCollectorClientOptions {
|
|
42
61
|
baseUrl: string;
|
|
43
62
|
projectId: string;
|
|
@@ -85,6 +104,7 @@ export declare class RemoteCollectorClient {
|
|
|
85
104
|
pendingRecordCount: number;
|
|
86
105
|
lastAckSequence?: number;
|
|
87
106
|
occurredAt?: string;
|
|
107
|
+
runtime?: CollectorRuntimeHeartbeat;
|
|
88
108
|
}): Promise<Record<string, unknown>>;
|
|
89
109
|
reconcile(runId: string, receipt: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
90
110
|
proposeAction(proposal: Record<string, unknown>, idempotencyKey: string): Promise<Record<string, unknown>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-collector.d.ts","sourceRoot":"","sources":["../../../../agentcert-sdk/src/remote-collector.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAeD,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,sCAAsC,CAAC;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IACxG,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7E;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,qCAAqC,CAAC;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACvC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,qBAAa,qBAAqB;IACZ,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAAE,OAAO,CAAC,KAAK;IAA5D,OAAO;WAEM,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,SAAwF,GAAG,OAAO,CAAC,qBAAqB,CAAC;WAY5K,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAOnE,IAAI,WAAW,IAAI,MAAM,CAAmC;IAE5D,YAAY,IAAI,oBAAoB;IAMpC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB;IAM9C,YAAY,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE;IAMpH,MAAM,CAAC,KAAK,SAA6F,GAAG,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;YAcpK,OAAO;CAOtB;AAED,qBAAa,qBAAqB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;gBAEhC,OAAO,EAAE,4BAA4B;IAQjD,iBAAiB,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAIhJ,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE,cAAc,SAAoD,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAQ5J,SAAS,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"remote-collector.d.ts","sourceRoot":"","sources":["../../../../agentcert-sdk/src/remote-collector.ts"],"names":[],"mappings":"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"}
|
|
@@ -104,6 +104,7 @@ export class RemoteCollectorClient {
|
|
|
104
104
|
occurredAt: input.occurredAt ?? new Date().toISOString(),
|
|
105
105
|
pendingRecordCount: input.pendingRecordCount,
|
|
106
106
|
lastAckSequence: input.lastAckSequence,
|
|
107
|
+
runtime: input.runtime,
|
|
107
108
|
};
|
|
108
109
|
const payloadSha256 = sha256(canonicalJson(payload));
|
|
109
110
|
return this.json("collector-heartbeats", {
|
package/dist/onboard.js
CHANGED
|
@@ -7,7 +7,9 @@ import { verifyControlPlaneConnection } from "./control-plane.js";
|
|
|
7
7
|
import { inferPrivateCapabilities, runPrivateCapabilityDiscovery } from "./private-discovery.js";
|
|
8
8
|
import { parseAgentTemplate, starterAdapter, starterProfile, starterTripwireConfig } from "./onboarding-templates.js";
|
|
9
9
|
import { writeTryEvidence } from "./try.js";
|
|
10
|
-
import { doctorCustomerGateway, initializeCustomerGateway, inspectCustomerGatewayFiles, startManagedCustomerGateway, stopManagedCustomerGateway, } from "./gateway.js";
|
|
10
|
+
import { doctorCustomerGateway, initializeCustomerGateway, inspectLocalRuntimeBinding, inspectCustomerGatewayFiles, startManagedCustomerGateway, stopManagedCustomerGateway, upgradeCustomerGatewayRuntime, RuntimeSetupNotReadyError, } from "./gateway.js";
|
|
11
|
+
import { discoverRuntimeReferences, planRuntimeSandboxModules } from "./runtime-sandbox-kit.js";
|
|
12
|
+
import { automaticRuntimeReferencesUsable, bootstrapLocalRuntime, verifyAutomaticRuntimeProbe } from "./runtime-bootstrap.js";
|
|
11
13
|
export async function runOnboard(options) {
|
|
12
14
|
const requestFetch = options.fetch ?? fetch;
|
|
13
15
|
const output = options.output ?? ((message) => process.stdout.write(message));
|
|
@@ -36,6 +38,44 @@ export async function runOnboard(options) {
|
|
|
36
38
|
if (!setupPlan || !setupPlan.authorizedOperations.some((item) => item.kind === "authorize_install")) {
|
|
37
39
|
throw new Error("Confirm the Setup Plan and authorize installation in the Witnora Workspace before running onboard.");
|
|
38
40
|
}
|
|
41
|
+
let localRuntime = await discoverRuntimeReferences({
|
|
42
|
+
repository: repositoryPath, configHome: options.configHome, projectId: token.projectId, server, env: options.env ?? process.env,
|
|
43
|
+
});
|
|
44
|
+
let runtimeLimitation = localRuntime.limitation;
|
|
45
|
+
let runtimeBootstrapRequired = !localRuntime.references;
|
|
46
|
+
if (localRuntime.references?.probeApiKeyId) {
|
|
47
|
+
try {
|
|
48
|
+
if (!await automaticRuntimeReferencesUsable(localRuntime.references))
|
|
49
|
+
throw new Error("local bootstrap material invalid");
|
|
50
|
+
await verifyAutomaticRuntimeProbe({ references: localRuntime.references, projectId: token.projectId, server, fetch: requestFetch });
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
runtimeBootstrapRequired = true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (runtimeBootstrapRequired) {
|
|
57
|
+
try {
|
|
58
|
+
const references = localRuntime.references;
|
|
59
|
+
const modules = references?.sandboxOrigin && references.adapterDigestSha256 && references.probeDigestSha256 && references.fixtureContractDigestSha256
|
|
60
|
+
? { sandboxOrigin: references.sandboxOrigin, adapterDigestSha256: references.adapterDigestSha256, probeDigestSha256: references.probeDigestSha256, fixtureContractDigestSha256: references.fixtureContractDigestSha256 }
|
|
61
|
+
: await planRuntimeSandboxModules();
|
|
62
|
+
const bootstrap = await bootstrapLocalRuntime({
|
|
63
|
+
projectId: token.projectId,
|
|
64
|
+
planId: setupPlan.id,
|
|
65
|
+
server,
|
|
66
|
+
apiKey: token.apiKey,
|
|
67
|
+
configHome: options.configHome,
|
|
68
|
+
fetch: requestFetch,
|
|
69
|
+
modules,
|
|
70
|
+
});
|
|
71
|
+
localRuntime = { references: bootstrap.references };
|
|
72
|
+
runtimeLimitation = undefined;
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
const detail = error instanceof Error ? error.message : "Unknown Runtime bootstrap error.";
|
|
76
|
+
runtimeLimitation = `Hosted Runtime bootstrap did not complete: ${detail.slice(0, 500)} The existing Gateway was preserved and setup remains RECORDED_ONLY.`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
39
79
|
const attemptId = `install-${Date.now()}-${randomSuffix()}`;
|
|
40
80
|
const generatedFiles = [];
|
|
41
81
|
const gatewayLifecycle = options.gatewayLifecycle ?? {
|
|
@@ -44,6 +84,7 @@ export async function runOnboard(options) {
|
|
|
44
84
|
};
|
|
45
85
|
let gatewayMigration;
|
|
46
86
|
let managedGateway;
|
|
87
|
+
let runtimeUpgrade;
|
|
47
88
|
await reportInstall(requestFetch, server, token.projectId, token.apiKey, setupPlan.id, { status: "installing", attemptId });
|
|
48
89
|
try {
|
|
49
90
|
generatedFiles.push(...await generateRepositoryConfig(repositoryPath, repository.template, repository.name));
|
|
@@ -84,17 +125,49 @@ export async function runOnboard(options) {
|
|
|
84
125
|
throw new Error(`Existing Gateway setup is incomplete. Preserve the existing files and repair or remove the partial setup in Advanced mode. Missing: ${gatewayState.missing.map((path) => basename(path)).join(", ")}.`);
|
|
85
126
|
}
|
|
86
127
|
if (gatewayState.status === "absent") {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
128
|
+
let gateway;
|
|
129
|
+
try {
|
|
130
|
+
gateway = await initializeCustomerGateway({
|
|
131
|
+
projectId: token.projectId, server, repository: repositoryPath, authorization: token,
|
|
132
|
+
runtimeReferences: localRuntime.references,
|
|
133
|
+
fetch: requestFetch, configHome: options.configHome, output,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (!(error instanceof RuntimeSetupNotReadyError) || !localRuntime.references)
|
|
138
|
+
throw error;
|
|
139
|
+
runtimeLimitation = `Local sandbox Runtime references were found but did not establish readiness: ${error.message}`;
|
|
140
|
+
gateway = await initializeCustomerGateway({ projectId: token.projectId, server, repository: repositoryPath, authorization: token, fetch: requestFetch, configHome: options.configHome, output });
|
|
141
|
+
}
|
|
91
142
|
generatedFiles.push(...gateway.generatedFiles);
|
|
92
143
|
}
|
|
93
144
|
else {
|
|
94
145
|
const binding = await inspectGatewayBinding(gatewayState.directory, token.projectId, server);
|
|
95
146
|
if (binding.matches) {
|
|
96
147
|
await saveConnection(binding.connectionName, { server, projectId: token.projectId, apiKey: token.apiKey }, { configHome: options.configHome });
|
|
97
|
-
|
|
148
|
+
if (localRuntime.references) {
|
|
149
|
+
try {
|
|
150
|
+
runtimeUpgrade = await upgradeCustomerGatewayRuntime({ repository: repositoryPath, authorization: token, runtimeReferences: localRuntime.references, configHome: options.configHome, fetch: requestFetch });
|
|
151
|
+
if (runtimeUpgrade.changed) {
|
|
152
|
+
const stopped = await gatewayLifecycle.stop({ repository: repositoryPath, configHome: options.configHome, fetch: requestFetch });
|
|
153
|
+
if (stopped.state !== "STOPPED" || stopped.healthy)
|
|
154
|
+
throw new Error("The prior managed Gateway process did not stop before Runtime generation replacement.");
|
|
155
|
+
}
|
|
156
|
+
runtimeLimitation = undefined;
|
|
157
|
+
output(runtimeUpgrade.changed
|
|
158
|
+
? "\nExisting customer-owned Gateway matches this project; safely replaced its generated Runtime generation, stopped the prior process, and preserved a local backup.\n"
|
|
159
|
+
: "\nExisting customer-owned Gateway already has the exact current Runtime generation; verifying and reusing it.\n");
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
if (!(error instanceof RuntimeSetupNotReadyError))
|
|
163
|
+
throw error;
|
|
164
|
+
runtimeLimitation = `Local sandbox Runtime references were found but did not establish readiness: ${error.message}`;
|
|
165
|
+
output("\nExisting customer-owned Gateway remains RECORDED_ONLY because its Runtime references did not pass readiness checks.\n");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
output("\nExisting customer-owned Gateway matches this project; verifying and reusing it.\n");
|
|
170
|
+
}
|
|
98
171
|
}
|
|
99
172
|
else {
|
|
100
173
|
await assertGatewayStopped(requestFetch, binding.host, binding.port, binding.projectId, token.projectId);
|
|
@@ -102,12 +175,14 @@ export async function runOnboard(options) {
|
|
|
102
175
|
output(`\nExisting Gateway belongs to project ${binding.projectId}; archived it at ${gatewayMigration.archiveDirectory}.\n`);
|
|
103
176
|
const gateway = await initializeCustomerGateway({
|
|
104
177
|
projectId: token.projectId, server, repository: repositoryPath, authorization: token,
|
|
178
|
+
runtimeReferences: localRuntime.references,
|
|
105
179
|
fetch: requestFetch, configHome: options.configHome, output,
|
|
106
180
|
});
|
|
107
181
|
generatedFiles.push(...gateway.generatedFiles);
|
|
108
182
|
}
|
|
109
183
|
}
|
|
110
|
-
|
|
184
|
+
const runtimeConfigured = await gatewayHasRuntimeWorker(repositoryPath);
|
|
185
|
+
generatedFiles.push(...await generateAutopilotFiles(repositoryPath, repository.name, runtimeConfigured));
|
|
111
186
|
managedGateway = await gatewayLifecycle.start({
|
|
112
187
|
repository: repositoryPath,
|
|
113
188
|
configHome: options.configHome,
|
|
@@ -117,10 +192,14 @@ export async function runOnboard(options) {
|
|
|
117
192
|
if (!managedGateway.healthy)
|
|
118
193
|
throw new Error(managedGateway.detail);
|
|
119
194
|
const doctor = await doctorCustomerGateway({ repository: repositoryPath, configHome: options.configHome, fetch: requestFetch });
|
|
120
|
-
if (doctor.overall !== "READY_TO_RECORD")
|
|
195
|
+
if (doctor.overall !== "READY_TO_RECORD" && doctor.overall !== "READY_FOR_RUNTIME")
|
|
121
196
|
throw new Error(doctor.checks.filter((check) => check.status === "FAIL").map((check) => check.message).join(" "));
|
|
197
|
+
const runtimeBinding = doctor.overall === "READY_FOR_RUNTIME" ? await inspectLocalRuntimeBinding({ repository: repositoryPath }).catch(() => undefined) : undefined;
|
|
198
|
+
const runtimeReadiness = doctor.overall === "READY_FOR_RUNTIME" && runtimeBinding
|
|
199
|
+
? { state: "LOCAL_SANDBOX_READY", checkedAt: new Date().toISOString(), limitations: [] }
|
|
200
|
+
: { state: "RECORDED_ONLY", checkedAt: new Date().toISOString(), limitations: [runtimeLimitation ?? "The local sandbox Runtime worker has not established exact adapter, probe, source-key, identity, mandate, and readiness bindings."] };
|
|
122
201
|
await reportInstall(requestFetch, server, token.projectId, token.apiKey, setupPlan.id, {
|
|
123
|
-
status: "verified", attemptId, generatedFiles: relativeGeneratedFiles(repositoryPath, generatedFiles),
|
|
202
|
+
status: "verified", attemptId, generatedFiles: relativeGeneratedFiles(repositoryPath, generatedFiles), runtimeReadiness, ...(runtimeBinding ? { runtimeBinding } : {}),
|
|
124
203
|
});
|
|
125
204
|
output(`\nWitnora Setup Autopilot completed for ${repository.name}.\n`);
|
|
126
205
|
output(`Project: ${token.projectId}\nTemplate: ${repository.template} (${repository.kind})\n`);
|
|
@@ -128,11 +207,14 @@ export async function runOnboard(options) {
|
|
|
128
207
|
output(`Private discovery: ${discovery.capabilityCount} capability group(s); ${discovery.unknownCapabilityCount} pending confirmation.\n`);
|
|
129
208
|
output("Installed: customer-owned Gateway, default-deny policy, independent-probe contract, review contract, and PR/release/nightly CI.\n");
|
|
130
209
|
output(`Gateway: ${managedGateway.state} at ${managedGateway.baseUrl}${managedGateway.pid ? ` (process ${managedGateway.pid})` : ""}.\n`);
|
|
210
|
+
output(runtimeReadiness.state === "LOCAL_SANDBOX_READY"
|
|
211
|
+
? "Runtime: LOCAL_SANDBOX_READY. This proves only the generated localhost sandbox loop is ready; it does not establish coverage, CURRENT, or a verified customer outcome.\n"
|
|
212
|
+
: `Runtime: RECORDED_ONLY. ${runtimeReadiness.limitations[0]}\n`);
|
|
131
213
|
output("The self-test remains isolated. The Gateway is ready in the background; run the agent normally. The first source-signed, server-reconciled Gateway run completes onboarding.\n");
|
|
132
214
|
return { projectId: token.projectId, connectionName: token.connectionName, credentialsPath, template: repository.template,
|
|
133
215
|
repositoryKind: repository.kind, generatedFiles, receiptPath, discovery, setupPlanId: setupPlan.id,
|
|
134
216
|
gatewayDirectory: join(repositoryPath, ".witnora", "gateway"), gatewayArchiveDirectory: gatewayMigration?.archiveDirectory,
|
|
135
|
-
gateway: managedGateway };
|
|
217
|
+
gateway: managedGateway, runtimeReadiness };
|
|
136
218
|
}
|
|
137
219
|
catch (error) {
|
|
138
220
|
const diagnosis = error instanceof Error ? error.message : String(error);
|
|
@@ -140,6 +222,7 @@ export async function runOnboard(options) {
|
|
|
140
222
|
await gatewayLifecycle.stop({ repository: repositoryPath, configHome: options.configHome, fetch: requestFetch }).catch(() => undefined);
|
|
141
223
|
}
|
|
142
224
|
await rollbackGeneratedFiles(generatedFiles);
|
|
225
|
+
await runtimeUpgrade?.rollback().catch(() => undefined);
|
|
143
226
|
if (gatewayMigration)
|
|
144
227
|
await restoreGateway(gatewayMigration);
|
|
145
228
|
await reportInstall(requestFetch, server, token.projectId, token.apiKey, setupPlan.id, {
|
|
@@ -199,10 +282,10 @@ async function restoreGateway(migration) {
|
|
|
199
282
|
function safePathSegment(value) {
|
|
200
283
|
return (value.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-|-$/g, "") || "unknown-project").slice(0, 80);
|
|
201
284
|
}
|
|
202
|
-
async function generateAutopilotFiles(repositoryPath, subject) {
|
|
285
|
+
async function generateAutopilotFiles(repositoryPath, subject, runtimeConfigured) {
|
|
203
286
|
const files = new Map([
|
|
204
287
|
[".witnora/setup/policy.json", `${JSON.stringify({ schemaVersion: "witnora.setup_policy.v0.1", subject, unknownCapabilities: "pending_confirmation", defaultDecision: "deny", environment: "sandbox" }, null, 2)}\n`],
|
|
205
|
-
[".witnora/setup/outcome-probe.json", `${JSON.stringify({ schemaVersion: "witnora.outcome_probe_contract.v0.1", mode: "independent_read_only",
|
|
288
|
+
[".witnora/setup/outcome-probe.json", `${JSON.stringify({ schemaVersion: "witnora.outcome_probe_contract.v0.1", mode: "independent_read_only", status: runtimeConfigured ? "configured" : "awaiting_runtime_bootstrap", uploadsCredential: false }, null, 2)}\n`],
|
|
206
289
|
[".witnora/setup/review.json", `${JSON.stringify({ schemaVersion: "witnora.review_contract.v0.1", independentReviewRequired: true, syntheticEvidenceEligible: false }, null, 2)}\n`],
|
|
207
290
|
[".github/workflows/witnora-assurance.yml", continuousAssuranceWorkflow()],
|
|
208
291
|
]);
|
|
@@ -217,6 +300,10 @@ async function generateAutopilotFiles(repositoryPath, subject) {
|
|
|
217
300
|
}
|
|
218
301
|
return written;
|
|
219
302
|
}
|
|
303
|
+
async function gatewayHasRuntimeWorker(repositoryPath) {
|
|
304
|
+
const config = await optionalJson(join(repositoryPath, ".witnora", "gateway", "gateway.json"));
|
|
305
|
+
return Boolean(config?.runtimeWorker && typeof config.runtimeWorker === "object" && !Array.isArray(config.runtimeWorker));
|
|
306
|
+
}
|
|
220
307
|
function continuousAssuranceWorkflow() {
|
|
221
308
|
return `name: Witnora assurance\non:\n pull_request:\n push:\n tags: [\"v*\"]\n schedule:\n - cron: \"17 3 * * *\"\n workflow_dispatch:\npermissions:\n contents: read\njobs:\n assurance:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-node@v4\n with:\n node-version: 22\n - run: npx witnora@latest release-gate --config witnora.config.json --strict\n`;
|
|
222
309
|
}
|