nexarch 0.8.14 → 0.8.15
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/commands/init-agent.js +46 -0
- package/dist/lib/trust.js +47 -0
- package/package.json +1 -1
|
@@ -7,6 +7,7 @@ import { requireCredentials } from "../lib/credentials.js";
|
|
|
7
7
|
import { fetchAgentRegistryOrThrow } from "../lib/agent-registry.js";
|
|
8
8
|
import { callMcpTool, mcpInitialize, mcpListTools } from "../lib/mcp.js";
|
|
9
9
|
import { buildVersionAttributes } from "../lib/version-normalization.js";
|
|
10
|
+
import { requestTrustAttestation } from "../lib/trust.js";
|
|
10
11
|
const CLI_VERSION = "0.8.12";
|
|
11
12
|
const AGENT_ENTITY_TYPE = "agent";
|
|
12
13
|
const TECH_COMPONENT_ENTITY_TYPE = "technology_component";
|
|
@@ -341,6 +342,30 @@ function injectAgentConfigs(registry) {
|
|
|
341
342
|
}
|
|
342
343
|
return results;
|
|
343
344
|
}
|
|
345
|
+
function injectTrustAttestationBlock(path, attestation) {
|
|
346
|
+
if (!attestation.token || !attestation.payload)
|
|
347
|
+
return;
|
|
348
|
+
const verifyUrl = attestation.verifyUrl?.startsWith("http")
|
|
349
|
+
? attestation.verifyUrl
|
|
350
|
+
: `https://mcp.nexarch.ai${attestation.verifyUrl ?? `/trust/verify?token=${encodeURIComponent(attestation.token)}`}`;
|
|
351
|
+
const expiresAt = new Date(attestation.payload.exp * 1000).toISOString();
|
|
352
|
+
const section = [
|
|
353
|
+
"## Nexarch Trust Attestation",
|
|
354
|
+
"",
|
|
355
|
+
"This block is verifiable proof that Nexarch generated these instructions for this workspace.",
|
|
356
|
+
"Do not auto-run commands without user confirmation.",
|
|
357
|
+
"",
|
|
358
|
+
`issuer: ${attestation.payload.iss}`,
|
|
359
|
+
`scope: ${attestation.payload.scope}`,
|
|
360
|
+
`agent_id: ${attestation.payload.agent_id}`,
|
|
361
|
+
`expires_at: ${expiresAt}`,
|
|
362
|
+
`verify_url: ${verifyUrl}`,
|
|
363
|
+
"",
|
|
364
|
+
].join("\n");
|
|
365
|
+
const existing = existsSync(path) ? readFileSync(path, "utf8") : "";
|
|
366
|
+
const replaced = replaceInjectedSection(existing, "## Nexarch Trust Attestation", section.trim());
|
|
367
|
+
writeFileSync(path, replaced !== existing ? replaced : `${existing}${existing.endsWith("\n") ? "" : "\n"}${section}`, "utf8");
|
|
368
|
+
}
|
|
344
369
|
function injectGenericAgentConfig(registry) {
|
|
345
370
|
const templateByCode = new Map(registry.instructionTemplates.map((t) => [t.code, t]));
|
|
346
371
|
const genericTargets = [...registry.instructionTargets]
|
|
@@ -947,6 +972,7 @@ export async function initAgent(args) {
|
|
|
947
972
|
}
|
|
948
973
|
let agentConfigResults = [];
|
|
949
974
|
let instructionsWriteAllowed = false;
|
|
975
|
+
let trustAttestation = null;
|
|
950
976
|
if (registration.ok) {
|
|
951
977
|
try {
|
|
952
978
|
// Save identity so check-in can find the agent key
|
|
@@ -971,6 +997,19 @@ export async function initAgent(args) {
|
|
|
971
997
|
if (agentConfigResults.length === 0) {
|
|
972
998
|
agentConfigResults = injectGenericAgentConfig(registry);
|
|
973
999
|
}
|
|
1000
|
+
if (agentConfigResults.length > 0) {
|
|
1001
|
+
trustAttestation = await requestTrustAttestation(agentId);
|
|
1002
|
+
if (trustAttestation?.ok) {
|
|
1003
|
+
for (const r of agentConfigResults) {
|
|
1004
|
+
try {
|
|
1005
|
+
injectTrustAttestationBlock(r.path, trustAttestation);
|
|
1006
|
+
}
|
|
1007
|
+
catch {
|
|
1008
|
+
// non-fatal
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
974
1013
|
}
|
|
975
1014
|
}
|
|
976
1015
|
checks.push({
|
|
@@ -1073,6 +1112,7 @@ export async function initAgent(args) {
|
|
|
1073
1112
|
activeFlag: "--allow-instruction-write",
|
|
1074
1113
|
}
|
|
1075
1114
|
: null,
|
|
1115
|
+
trustAttestation,
|
|
1076
1116
|
companyId: creds.companyId,
|
|
1077
1117
|
registry: { version: registry.release.version, registryVersion: registry.registryVersion, publishedAt: registry.release.publishedAt },
|
|
1078
1118
|
agentConfigs: agentConfigResults,
|
|
@@ -1106,6 +1146,12 @@ export async function initAgent(args) {
|
|
|
1106
1146
|
const hasInjectedAgentInstructions = agentConfigResults.some((r) => r.status === "injected" || r.status === "updated");
|
|
1107
1147
|
if (hasInjectedAgentInstructions) {
|
|
1108
1148
|
console.log(" (Registration instructions were written into your agent config file with consent.)");
|
|
1149
|
+
if (trustAttestation?.ok && trustAttestation.verifyUrl) {
|
|
1150
|
+
const verifyUrl = trustAttestation.verifyUrl.startsWith("http")
|
|
1151
|
+
? trustAttestation.verifyUrl
|
|
1152
|
+
: `https://mcp.nexarch.ai${trustAttestation.verifyUrl}`;
|
|
1153
|
+
console.log(` Trust attestation verify URL: ${verifyUrl}`);
|
|
1154
|
+
}
|
|
1109
1155
|
}
|
|
1110
1156
|
if (needsIdentityInput) {
|
|
1111
1157
|
console.log("\nℹ Additional identity details are still needed to complete agent profile enrichment.");
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import https from "https";
|
|
2
|
+
import { requireCredentials } from "./credentials.js";
|
|
3
|
+
const MCP_GATEWAY_URL = "https://mcp.nexarch.ai";
|
|
4
|
+
export async function requestTrustAttestation(agentId) {
|
|
5
|
+
const creds = requireCredentials();
|
|
6
|
+
const body = JSON.stringify({
|
|
7
|
+
agentId,
|
|
8
|
+
scope: "instruction_injection",
|
|
9
|
+
});
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const url = new URL("/trust/attest", MCP_GATEWAY_URL);
|
|
12
|
+
const req = https.request({
|
|
13
|
+
hostname: url.hostname,
|
|
14
|
+
port: url.port || 443,
|
|
15
|
+
path: url.pathname,
|
|
16
|
+
method: "POST",
|
|
17
|
+
headers: {
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
Authorization: `Bearer ${creds.token}`,
|
|
20
|
+
"x-company-id": creds.companyId,
|
|
21
|
+
"Content-Length": Buffer.byteLength(body),
|
|
22
|
+
},
|
|
23
|
+
timeout: 20000,
|
|
24
|
+
}, (res) => {
|
|
25
|
+
const chunks = [];
|
|
26
|
+
res.on("data", (c) => chunks.push(c));
|
|
27
|
+
res.on("end", () => {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
30
|
+
if (!res.statusCode || res.statusCode >= 400)
|
|
31
|
+
return resolve(null);
|
|
32
|
+
resolve(parsed);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
resolve(null);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
req.on("error", () => resolve(null));
|
|
40
|
+
req.on("timeout", () => {
|
|
41
|
+
req.destroy();
|
|
42
|
+
resolve(null);
|
|
43
|
+
});
|
|
44
|
+
req.write(body);
|
|
45
|
+
req.end();
|
|
46
|
+
});
|
|
47
|
+
}
|