witnora 0.20.14 → 0.20.16
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/credentials.js
CHANGED
|
@@ -68,7 +68,8 @@ export function resolveOnboardServer(options) {
|
|
|
68
68
|
const server = env.WITNORA_BASE_URL ?? env.AGENTCERT_BASE_URL;
|
|
69
69
|
const projectId = env.WITNORA_BASE_URL !== undefined ? env.WITNORA_PROJECT_ID : env.AGENTCERT_PROJECT_ID;
|
|
70
70
|
if (server && projectId && projectId !== options.projectId) {
|
|
71
|
-
|
|
71
|
+
const projectVariable = env.WITNORA_BASE_URL !== undefined ? "WITNORA_PROJECT_ID" : "AGENTCERT_PROJECT_ID";
|
|
72
|
+
throw new Error(`Onboarding project "${options.projectId}" differs from environment project "${projectId}". Update or unset ${projectVariable}, or pass --server <url> explicitly to choose the intended server; no authorization request was sent.`);
|
|
72
73
|
}
|
|
73
74
|
return normalizeServer(server ?? DEFAULT_WITNORA_SERVER);
|
|
74
75
|
}
|
|
@@ -89,7 +90,8 @@ function validateConnection(input) {
|
|
|
89
90
|
throw new Error("Witnora project ID is required.");
|
|
90
91
|
if (!apiKey.startsWith("ac_live_"))
|
|
91
92
|
throw new Error("Witnora API key must start with ac_live_.");
|
|
92
|
-
|
|
93
|
+
const approvedSetupPlanId = input.approvedSetupPlanId?.trim();
|
|
94
|
+
return { server: normalizeServer(input.server), projectId, apiKey, ...(approvedSetupPlanId ? { approvedSetupPlanId } : {}) };
|
|
93
95
|
}
|
|
94
96
|
function normalizeServer(value) {
|
|
95
97
|
let url;
|
|
@@ -25,6 +25,7 @@ export async function authorizeProjectConnection(options) {
|
|
|
25
25
|
server,
|
|
26
26
|
projectId: token.projectId,
|
|
27
27
|
apiKey: token.apiKey,
|
|
28
|
+
approvedSetupPlanId: token.approvedSetupPlanId,
|
|
28
29
|
}, { configHome: options.configHome });
|
|
29
30
|
return { ...token, server, credentialsPath };
|
|
30
31
|
}
|
package/dist/onboard.js
CHANGED
|
@@ -48,18 +48,19 @@ export async function runOnboard(options) {
|
|
|
48
48
|
configHome: options.configHome,
|
|
49
49
|
});
|
|
50
50
|
if (reusableConnection)
|
|
51
|
-
output("Reusing
|
|
51
|
+
output("Reusing this Agent's previously approved setup connection; verifying its exact Setup Plan.\n");
|
|
52
52
|
const credentialsPath = token.credentialsPath;
|
|
53
53
|
await verifyControlPlaneConnection({ baseUrl: server, projectId: token.projectId, apiKey: token.apiKey, fetch: requestFetch });
|
|
54
|
-
const
|
|
54
|
+
const planQuery = token.approvedSetupPlanId ? `?setupPlanId=${encodeURIComponent(token.approvedSetupPlanId)}` : "";
|
|
55
|
+
const planSnapshot = await jsonRequest(requestFetch, `${server}/v1/projects/${encodeURIComponent(token.projectId)}/setup-plans${planQuery}`, {
|
|
55
56
|
method: "GET", headers: { authorization: `Bearer ${token.apiKey}` },
|
|
56
57
|
});
|
|
57
58
|
const setupPlan = planSnapshot.plan;
|
|
58
|
-
if (!setupPlan || !setupPlan.authorizedOperations.some((item) => item.kind === "authorize_install")) {
|
|
59
|
+
if (!setupPlan || (token.approvedSetupPlanId && setupPlan.id !== token.approvedSetupPlanId) || !setupPlan.authorizedOperations.some((item) => item.kind === "authorize_install")) {
|
|
59
60
|
throw new Error("Confirm the Setup Plan and authorize installation in the Witnora Workspace before running onboard.");
|
|
60
61
|
}
|
|
61
62
|
let localRuntime = await discoverRuntimeReferences({
|
|
62
|
-
repository: repositoryPath, configHome: options.configHome, projectId: token.projectId, server, env: options.env ?? process.env,
|
|
63
|
+
repository: repositoryPath, configHome: options.configHome, projectId: token.projectId, setupPlanId: setupPlan.id, server, env: options.env ?? process.env,
|
|
63
64
|
});
|
|
64
65
|
let runtimeLimitation = localRuntime.limitation;
|
|
65
66
|
let runtimeBootstrapRequired = !localRuntime.references;
|
|
@@ -205,7 +206,7 @@ export async function runOnboard(options) {
|
|
|
205
206
|
else {
|
|
206
207
|
const binding = await inspectGatewayBinding(gatewayState.directory, token.projectId, server);
|
|
207
208
|
if (binding.matches) {
|
|
208
|
-
await saveConnection(binding.connectionName, { server, projectId: token.projectId, apiKey: token.apiKey }, { configHome: options.configHome });
|
|
209
|
+
await saveConnection(binding.connectionName, { server, projectId: token.projectId, apiKey: token.apiKey, approvedSetupPlanId: setupPlan.id }, { configHome: options.configHome });
|
|
209
210
|
if (localRuntime.references) {
|
|
210
211
|
try {
|
|
211
212
|
runtimeUpgrade = await prepareRuntime(() => upgradeCustomerGatewayRuntime({ repository: repositoryPath, authorization: token, runtimeReferences: localRuntime.references, agentIdentity, configHome: options.configHome, fetch: requestFetch }));
|
|
@@ -3,7 +3,7 @@ import { chmod, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises"
|
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
5
|
import { credentialsPath } from "./credentials.js";
|
|
6
|
-
import { saveRuntimeReferenceManifest } from "./runtime-sandbox-kit.js";
|
|
6
|
+
import { runtimeReferenceManifestPath, saveRuntimeReferenceManifest } from "./runtime-sandbox-kit.js";
|
|
7
7
|
const SCHEMA_VERSION = "witnora.runtime_bootstrap.v0.1";
|
|
8
8
|
const ENVELOPE_ALGORITHM = "X25519-HKDF-SHA256-A256GCM";
|
|
9
9
|
const PROBE_SCOPES = ["outcomes:verify"];
|
|
@@ -85,6 +85,7 @@ export async function bootstrapLocalRuntime(input) {
|
|
|
85
85
|
await acknowledge(requestFetch, endpoint, input.apiKey, issued.bootstrapId, issued.envelope.digestSha256);
|
|
86
86
|
const manifestPath = join(dirname(credentialsPath({ configHome: input.configHome })), "runtime-references.json");
|
|
87
87
|
await saveRuntimeReferenceManifest(manifestPath, input.projectId, server, references);
|
|
88
|
+
await saveRuntimeReferenceManifest(runtimeReferenceManifestPath({ ...input, server, setupPlanId: input.planId }), input.projectId, server, references);
|
|
88
89
|
await rm(attemptPath, { force: true });
|
|
89
90
|
return { references, bootstrapId: issued.bootstrapId };
|
|
90
91
|
}
|
|
@@ -16,15 +16,26 @@ export async function discoverRuntimeReferences(input) {
|
|
|
16
16
|
runtimeKeyId: input.env.WITNORA_RUNTIME_KEY_ID?.trim(),
|
|
17
17
|
runtimeSigningKeyHandle: input.env.WITNORA_RUNTIME_SIGNING_KEY_HANDLE?.trim(),
|
|
18
18
|
};
|
|
19
|
-
const manifestPath =
|
|
20
|
-
const
|
|
19
|
+
const manifestPath = runtimeReferenceManifestPath(input);
|
|
20
|
+
const legacyManifestPath = join(dirname(credentialsPath({ configHome: input.configHome })), "runtime-references.json");
|
|
21
|
+
const gateway = input.setupPlanId ? await optionalJson(join(input.repository, ".witnora", "gateway", "gateway.json")) : undefined;
|
|
22
|
+
const worker = object(gateway?.runtimeWorker);
|
|
23
|
+
const gatewayReferences = gateway?.projectId === input.projectId && gateway.server === input.server && worker.runtimeSetupPlanId === input.setupPlanId
|
|
24
|
+
? completeReferences({ ...worker, setupPlanId: worker.runtimeSetupPlanId, bootstrapId: worker.runtimeBootstrapId,
|
|
25
|
+
adapterDigestSha256: worker.adapterModuleSha256, probeDigestSha256: worker.probeModuleSha256, fixtureContractDigestSha256: worker.fixtureContractSha256 })
|
|
26
|
+
: undefined;
|
|
27
|
+
const manifest = await optionalJson(manifestPath) ?? (gatewayReferences
|
|
28
|
+
? { schemaVersion: "witnora.runtime_references.v0.1", projectId: input.projectId, server: input.server, references: gatewayReferences }
|
|
29
|
+
: await optionalJson(legacyManifestPath));
|
|
21
30
|
const manifestReferences = manifest?.schemaVersion === "witnora.runtime_references.v0.1" && manifest.projectId === input.projectId && manifest.server === input.server
|
|
22
31
|
? completeReferences(manifest.references)
|
|
23
32
|
: undefined;
|
|
33
|
+
const matchingReferences = !input.setupPlanId || !manifestReferences?.probeApiKeyId || manifestReferences.setupPlanId === input.setupPlanId
|
|
34
|
+
? manifestReferences : undefined;
|
|
24
35
|
const environmentOverrides = Object.fromEntries(Object.entries(entries).filter(([, value]) => value));
|
|
25
|
-
const configuredReferences = completeReferences({ ...
|
|
36
|
+
const configuredReferences = completeReferences({ ...matchingReferences, ...environmentOverrides });
|
|
26
37
|
if (configuredReferences) {
|
|
27
|
-
if (Object.keys(environmentOverrides).length > 0)
|
|
38
|
+
if (input.setupPlanId || Object.keys(environmentOverrides).length > 0)
|
|
28
39
|
await saveRuntimeReferenceManifest(manifestPath, input.projectId, input.server, configuredReferences);
|
|
29
40
|
return { references: configuredReferences, manifestPath };
|
|
30
41
|
}
|
|
@@ -48,6 +59,13 @@ export async function discoverRuntimeReferences(input) {
|
|
|
48
59
|
? `Local sandbox Runtime references are incomplete (${present.join(", ")} present). Existing Gateway setup remains RECORDED_ONLY.`
|
|
49
60
|
: "No existing private Witnora Runtime reference manifest was found. Gateway setup remains RECORDED_ONLY until Hosted bootstrap can issue one-time Runtime references." };
|
|
50
61
|
}
|
|
62
|
+
export function runtimeReferenceManifestPath(input) {
|
|
63
|
+
const root = dirname(credentialsPath({ configHome: input.configHome }));
|
|
64
|
+
if (!input.setupPlanId)
|
|
65
|
+
return join(root, "runtime-references.json");
|
|
66
|
+
const bindingId = createHash("sha256").update(JSON.stringify([normalizeServer(input.server), input.projectId, input.setupPlanId])).digest("hex");
|
|
67
|
+
return join(root, "runtime-bootstrap", bindingId, "runtime-references.json");
|
|
68
|
+
}
|
|
51
69
|
function completeReferences(value) {
|
|
52
70
|
const mandateId = text(value.mandateId);
|
|
53
71
|
const runtimeIdentityId = text(value.runtimeIdentityId);
|