nexarch 0.6.6 → 0.7.1

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.
@@ -1,3 +1,4 @@
1
+ import { existsSync, readFileSync } from "fs";
1
2
  import process from "process";
2
3
  import { requireCredentials } from "../lib/credentials.js";
3
4
  import { callMcpTool } from "../lib/mcp.js";
@@ -19,7 +20,16 @@ function parseToolText(result) {
19
20
  export async function commandDone(args) {
20
21
  const asJson = parseFlag(args, "--json");
21
22
  const id = parseOptionValue(args, "--id");
22
- const summary = parseOptionValue(args, "--summary");
23
+ const summaryArg = parseOptionValue(args, "--summary");
24
+ const summaryFile = parseOptionValue(args, "--summary-file");
25
+ let summary = summaryArg;
26
+ if (summaryFile) {
27
+ if (!existsSync(summaryFile)) {
28
+ console.error(`error: --summary-file not found: ${summaryFile}`);
29
+ process.exit(1);
30
+ }
31
+ summary = readFileSync(summaryFile, "utf8");
32
+ }
23
33
  if (!id) {
24
34
  console.error("error: --id <commandId> is required");
25
35
  process.exit(1);
@@ -83,18 +83,23 @@ function parseFindings(args) {
83
83
  }
84
84
  return parsed.map((item) => {
85
85
  const value = item;
86
+ const policyControlId = String(value.policyControlId ?? value.controlId ?? "").trim();
87
+ const policyRuleId = String(value.policyRuleId ?? value.ruleId ?? "").trim();
86
88
  const result = String(value.result ?? "").toLowerCase();
87
- if (!value.policyControlId || !value.policyRuleId || !result) {
88
- throw new Error("Each finding must include policyControlId, policyRuleId, result");
89
+ if (!policyControlId || !policyRuleId || !result) {
90
+ throw new Error("Each finding must include policyControlId, policyRuleId, result. Tip: run 'nexarch policy-controls --entity <application:key> --json' and use the rule IDs from controls[].rules[].id");
89
91
  }
90
92
  if (result !== "pass" && result !== "partial" && result !== "fail") {
91
93
  throw new Error(`Invalid finding result '${String(value.result)}'. Use pass|partial|fail.`);
92
94
  }
95
+ const rationale = value.rationale
96
+ ? String(value.rationale)
97
+ : [value.summary, value.evidence].filter(Boolean).map(String).join("\n\n");
93
98
  return {
94
- policyControlId: String(value.policyControlId),
95
- policyRuleId: String(value.policyRuleId),
99
+ policyControlId,
100
+ policyRuleId,
96
101
  result,
97
- ...(value.rationale ? { rationale: String(value.rationale) } : {}),
102
+ ...(rationale ? { rationale } : {}),
98
103
  ...(Array.isArray(value.missingRequirements) ? { missingRequirements: value.missingRequirements.map(String) } : {}),
99
104
  };
100
105
  });
@@ -107,6 +112,27 @@ function parseFindings(args) {
107
112
  }
108
113
  export async function policyAuditSubmit(args) {
109
114
  const asJson = parseFlag(args, "--json");
115
+ if (parseFlag(args, "--help") || parseFlag(args, "-h")) {
116
+ console.log(`
117
+ Usage:
118
+ nexarch policy-audit-submit --command-id <id> --application-key <key> [options]
119
+
120
+ Options:
121
+ --command-id <id> Required command id
122
+ --application-key <key> Required application key (e.g. application:bad-driving)
123
+ --agent-key <key> Optional agent key (defaults from identity)
124
+ --finding <controlId|ruleId|result|rationale|missing1;missing2> Repeatable
125
+ --findings-json <json> JSON array of findings
126
+ --findings-file <path> Path to JSON array of findings
127
+ --json Print JSON response
128
+
129
+ Notes:
130
+ - Findings are rule-level (policyRuleId is required).
131
+ - You can submit partial findings multiple times for the same command.
132
+ - Get valid rule ids with: nexarch policy-controls --entity <application:key> --json
133
+ `);
134
+ return;
135
+ }
110
136
  const commandId = parseOptionValue(args, "--command-id") ?? parseOptionValue(args, "--id");
111
137
  const applicationEntityKey = parseOptionValue(args, "--application-key") ?? parseOptionValue(args, "--entity");
112
138
  const agentKey = parseOptionValue(args, "--agent-key") ?? loadIdentityAgentKey();
@@ -0,0 +1,95 @@
1
+ import process from "process";
2
+ import { writeFileSync } from "fs";
3
+ import { requireCredentials } from "../lib/credentials.js";
4
+ import { callMcpTool } from "../lib/mcp.js";
5
+ function parseFlag(args, flag) {
6
+ return args.includes(flag);
7
+ }
8
+ function parseOptionValue(args, option) {
9
+ const idx = args.indexOf(option);
10
+ if (idx === -1)
11
+ return null;
12
+ const v = args[idx + 1];
13
+ if (!v || v.startsWith("--"))
14
+ return null;
15
+ return v;
16
+ }
17
+ function parseMultiOptionValues(args, option) {
18
+ const values = [];
19
+ for (let i = 0; i < args.length; i += 1) {
20
+ if (args[i] !== option)
21
+ continue;
22
+ const v = args[i + 1];
23
+ if (!v || v.startsWith("--"))
24
+ continue;
25
+ values.push(v);
26
+ }
27
+ return values;
28
+ }
29
+ function parseToolText(result) {
30
+ const text = result.content?.[0]?.text ?? "{}";
31
+ return JSON.parse(text);
32
+ }
33
+ export async function policyAuditTemplate(args) {
34
+ const asJson = parseFlag(args, "--json");
35
+ const entity = parseOptionValue(args, "--entity") ?? parseOptionValue(args, "--application-key");
36
+ const outputPath = parseOptionValue(args, "--out") ?? parseOptionValue(args, "--output");
37
+ const defaultResult = (parseOptionValue(args, "--default-result") ?? "fail").toLowerCase();
38
+ const selectedControlIds = new Set(parseMultiOptionValues(args, "--control-id"));
39
+ if (parseFlag(args, "--help") || parseFlag(args, "-h")) {
40
+ console.log(`
41
+ Usage:
42
+ nexarch policy-audit-template --entity <application:key> [options]
43
+
44
+ Options:
45
+ --entity <key> Required (e.g. application:bad-driving)
46
+ --control-id <uuid> Optional repeatable filter (selected controls only)
47
+ --default-result <value> pass|partial|fail (default: fail)
48
+ --output, --out <path.json> Write findings array to file
49
+ --json Print JSON to stdout
50
+
51
+ Output shape is ready for:
52
+ nexarch policy-audit-submit --findings-file <path.json>
53
+ `);
54
+ return;
55
+ }
56
+ if (!entity) {
57
+ console.error("error: --entity <externalKey> is required (e.g. application:bad-driving)");
58
+ process.exit(1);
59
+ }
60
+ if (!["pass", "partial", "fail"].includes(defaultResult)) {
61
+ console.error("error: --default-result must be pass|partial|fail");
62
+ process.exit(1);
63
+ }
64
+ const creds = requireCredentials();
65
+ const raw = await callMcpTool("nexarch_get_entity_policy_controls", { entityExternalKey: entity, companyId: creds.companyId }, { companyId: creds.companyId });
66
+ const result = parseToolText(raw);
67
+ if (!result.found) {
68
+ console.error(`error: entity not found: ${entity}`);
69
+ process.exit(1);
70
+ }
71
+ const findings = (result.controls ?? [])
72
+ .filter((control) => selectedControlIds.size === 0 || selectedControlIds.has(control.id))
73
+ .flatMap((control) => (control.rules ?? []).map((rule) => ({
74
+ policyControlId: control.id,
75
+ policyRuleId: rule.id,
76
+ result: defaultResult,
77
+ rationale: "",
78
+ missingRequirements: [],
79
+ })));
80
+ if (findings.length === 0) {
81
+ console.error("error: no rules found for selected controls/entity");
82
+ process.exit(1);
83
+ }
84
+ const payload = JSON.stringify(findings, null, 2);
85
+ if (outputPath) {
86
+ writeFileSync(outputPath, `${payload}\n`, "utf8");
87
+ if (!asJson) {
88
+ console.log(`Template written: ${outputPath}`);
89
+ console.log(`Findings: ${findings.length}`);
90
+ }
91
+ }
92
+ if (asJson || !outputPath) {
93
+ process.stdout.write(`${payload}\n`);
94
+ }
95
+ }
package/dist/index.js CHANGED
@@ -17,6 +17,7 @@ import { commandDone } from "./commands/command-done.js";
17
17
  import { commandFail } from "./commands/command-fail.js";
18
18
  import { commandClaim } from "./commands/command-claim.js";
19
19
  import { policyControls } from "./commands/policy-controls.js";
20
+ import { policyAuditTemplate } from "./commands/policy-audit-template.js";
20
21
  import { policyAuditSubmit } from "./commands/policy-audit-submit.js";
21
22
  const [, , command, ...args] = process.argv;
22
23
  const commands = {
@@ -38,6 +39,7 @@ const commands = {
38
39
  "command-fail": commandFail,
39
40
  "command-claim": commandClaim,
40
41
  "policy-controls": policyControls,
42
+ "policy-audit-template": policyAuditTemplate,
41
43
  "policy-audit-submit": policyAuditSubmit,
42
44
  };
43
45
  async function main() {
@@ -132,6 +134,7 @@ Usage:
132
134
  Mark a claimed command as completed.
133
135
  Options: --id <commandId> (required)
134
136
  --summary <text> short summary of what was done
137
+ --summary-file <path.md|txt>
135
138
  --json
136
139
  nexarch command-fail
137
140
  Mark a claimed command as failed.
@@ -142,6 +145,13 @@ Usage:
142
145
  Fetch policy controls/rules assigned to an entity (for policy audits).
143
146
  Options: --entity <externalKey> (required, e.g. application:bad-driving)
144
147
  --json
148
+ nexarch policy-audit-template
149
+ Generate a findings JSON template from policy controls/rules for an entity.
150
+ Options: --entity <externalKey> (required)
151
+ --control-id <uuid> (repeatable; optional filter)
152
+ --default-result <pass|partial|fail> (default: fail)
153
+ --output <path.json>
154
+ --json
145
155
  nexarch policy-audit-submit
146
156
  Submit structured policy findings (writes policy_audit_finding rows).
147
157
  Options: --command-id <id> (required)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexarch",
3
- "version": "0.6.6",
3
+ "version": "0.7.1",
4
4
  "description": "Your architecture workspace for AI delivery.",
5
5
  "keywords": [
6
6
  "nexarch",