@orygn/opa-mcp 0.4.0 → 0.6.0
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 +583 -4
- package/README.md +144 -98
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +9 -3
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +14 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +91 -19
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +1 -6
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +17 -3
- package/dist/constants.js.map +1 -1
- package/dist/lib/bundle-signatures.d.ts +23 -0
- package/dist/lib/bundle-signatures.d.ts.map +1 -0
- package/dist/lib/bundle-signatures.js +152 -0
- package/dist/lib/bundle-signatures.js.map +1 -0
- package/dist/lib/child-env.d.ts +9 -2
- package/dist/lib/child-env.d.ts.map +1 -1
- package/dist/lib/child-env.js +38 -6
- package/dist/lib/child-env.js.map +1 -1
- package/dist/lib/conftest-cli.d.ts +25 -10
- package/dist/lib/conftest-cli.d.ts.map +1 -1
- package/dist/lib/conftest-cli.js +233 -50
- package/dist/lib/conftest-cli.js.map +1 -1
- package/dist/lib/errors.d.ts +4 -5
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +15 -3
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/inline-paths.d.ts +37 -0
- package/dist/lib/inline-paths.d.ts.map +1 -0
- package/dist/lib/inline-paths.js +162 -0
- package/dist/lib/inline-paths.js.map +1 -0
- package/dist/lib/install-id.d.ts.map +1 -1
- package/dist/lib/install-id.js +18 -3
- package/dist/lib/install-id.js.map +1 -1
- package/dist/lib/json-stream.d.ts +26 -0
- package/dist/lib/json-stream.d.ts.map +1 -0
- package/dist/lib/json-stream.js +69 -0
- package/dist/lib/json-stream.js.map +1 -0
- package/dist/lib/opa-cli.d.ts +74 -16
- package/dist/lib/opa-cli.d.ts.map +1 -1
- package/dist/lib/opa-cli.js +107 -30
- package/dist/lib/opa-cli.js.map +1 -1
- package/dist/lib/opa-client.d.ts +27 -1
- package/dist/lib/opa-client.d.ts.map +1 -1
- package/dist/lib/opa-client.js +98 -14
- package/dist/lib/opa-client.js.map +1 -1
- package/dist/lib/opa-paths.d.ts +34 -0
- package/dist/lib/opa-paths.d.ts.map +1 -0
- package/dist/lib/opa-paths.js +101 -0
- package/dist/lib/opa-paths.js.map +1 -0
- package/dist/lib/output.d.ts.map +1 -1
- package/dist/lib/output.js +83 -10
- package/dist/lib/output.js.map +1 -1
- package/dist/lib/regal-cli.d.ts +16 -1
- package/dist/lib/regal-cli.d.ts.map +1 -1
- package/dist/lib/regal-cli.js +40 -6
- package/dist/lib/regal-cli.js.map +1 -1
- package/dist/lib/rego-ast-walker.d.ts +0 -6
- package/dist/lib/rego-ast-walker.d.ts.map +1 -1
- package/dist/lib/rego-ast-walker.js +181 -55
- package/dist/lib/rego-ast-walker.js.map +1 -1
- package/dist/lib/rego-counterexample.d.ts +15 -2
- package/dist/lib/rego-counterexample.d.ts.map +1 -1
- package/dist/lib/rego-counterexample.js +63 -15
- package/dist/lib/rego-counterexample.js.map +1 -1
- package/dist/lib/rego-input-path.d.ts +20 -0
- package/dist/lib/rego-input-path.d.ts.map +1 -0
- package/dist/lib/rego-input-path.js +70 -0
- package/dist/lib/rego-input-path.js.map +1 -0
- package/dist/lib/rego-ir.d.ts +34 -3
- package/dist/lib/rego-ir.d.ts.map +1 -1
- package/dist/lib/rego-smt-encoder.d.ts +88 -5
- package/dist/lib/rego-smt-encoder.d.ts.map +1 -1
- package/dist/lib/rego-smt-encoder.js +270 -31
- package/dist/lib/rego-smt-encoder.js.map +1 -1
- package/dist/lib/rego-type-inferencer.d.ts +27 -2
- package/dist/lib/rego-type-inferencer.d.ts.map +1 -1
- package/dist/lib/rego-type-inferencer.js +71 -3
- package/dist/lib/rego-type-inferencer.js.map +1 -1
- package/dist/lib/rego-verify-engine.d.ts.map +1 -1
- package/dist/lib/rego-verify-engine.js +203 -90
- package/dist/lib/rego-verify-engine.js.map +1 -1
- package/dist/lib/rego-z3.d.ts +66 -0
- package/dist/lib/rego-z3.d.ts.map +1 -1
- package/dist/lib/rego-z3.js +312 -5
- package/dist/lib/rego-z3.js.map +1 -1
- package/dist/lib/security.d.ts +8 -0
- package/dist/lib/security.d.ts.map +1 -1
- package/dist/lib/security.js +130 -54
- package/dist/lib/security.js.map +1 -1
- package/dist/lib/subprocess.d.ts +13 -0
- package/dist/lib/subprocess.d.ts.map +1 -1
- package/dist/lib/subprocess.js +153 -18
- package/dist/lib/subprocess.js.map +1 -1
- package/dist/lib/tool-helpers.d.ts +12 -25
- package/dist/lib/tool-helpers.d.ts.map +1 -1
- package/dist/lib/tool-helpers.js +66 -40
- package/dist/lib/tool-helpers.js.map +1 -1
- package/dist/prompts/index.js +2 -2
- package/dist/resources/index.js +1 -1
- package/dist/resources/index.js.map +1 -1
- package/dist/resources/patterns.d.ts +1 -1
- package/dist/resources/patterns.d.ts.map +1 -1
- package/dist/resources/patterns.js +42 -15
- package/dist/resources/patterns.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +50 -7
- package/dist/server.js.map +1 -1
- package/dist/tools/authoring/capabilities.d.ts +4 -0
- package/dist/tools/authoring/capabilities.d.ts.map +1 -1
- package/dist/tools/authoring/capabilities.js +41 -4
- package/dist/tools/authoring/capabilities.js.map +1 -1
- package/dist/tools/authoring/check-schema.d.ts +6 -0
- package/dist/tools/authoring/check-schema.d.ts.map +1 -1
- package/dist/tools/authoring/check-schema.js +56 -3
- package/dist/tools/authoring/check-schema.js.map +1 -1
- package/dist/tools/authoring/format.d.ts.map +1 -1
- package/dist/tools/authoring/format.js +2 -2
- package/dist/tools/authoring/format.js.map +1 -1
- package/dist/tools/authoring/lint.d.ts.map +1 -1
- package/dist/tools/authoring/lint.js +8 -6
- package/dist/tools/authoring/lint.js.map +1 -1
- package/dist/tools/authoring/migrate-v1.d.ts.map +1 -1
- package/dist/tools/authoring/migrate-v1.js +20 -4
- package/dist/tools/authoring/migrate-v1.js.map +1 -1
- package/dist/tools/authoring/parse.d.ts.map +1 -1
- package/dist/tools/authoring/parse.js +3 -3
- package/dist/tools/authoring/parse.js.map +1 -1
- package/dist/tools/bundles/build.d.ts.map +1 -1
- package/dist/tools/bundles/build.js +12 -4
- package/dist/tools/bundles/build.js.map +1 -1
- package/dist/tools/bundles/sign.d.ts +9 -2
- package/dist/tools/bundles/sign.d.ts.map +1 -1
- package/dist/tools/bundles/sign.js +125 -19
- package/dist/tools/bundles/sign.js.map +1 -1
- package/dist/tools/bundles/verify.d.ts +1 -1
- package/dist/tools/bundles/verify.d.ts.map +1 -1
- package/dist/tools/bundles/verify.js +58 -19
- package/dist/tools/bundles/verify.js.map +1 -1
- package/dist/tools/conftest/index.d.ts +5 -0
- package/dist/tools/conftest/index.d.ts.map +1 -1
- package/dist/tools/conftest/index.js.map +1 -1
- package/dist/tools/conftest/pull.d.ts.map +1 -1
- package/dist/tools/conftest/pull.js +24 -10
- package/dist/tools/conftest/pull.js.map +1 -1
- package/dist/tools/conftest/push.d.ts.map +1 -1
- package/dist/tools/conftest/push.js +17 -7
- package/dist/tools/conftest/push.js.map +1 -1
- package/dist/tools/conftest/test.d.ts +10 -6
- package/dist/tools/conftest/test.d.ts.map +1 -1
- package/dist/tools/conftest/test.js +61 -39
- package/dist/tools/conftest/test.js.map +1 -1
- package/dist/tools/conftest/verify.d.ts +10 -6
- package/dist/tools/conftest/verify.d.ts.map +1 -1
- package/dist/tools/conftest/verify.js +40 -32
- package/dist/tools/conftest/verify.js.map +1 -1
- package/dist/tools/evaluation/_shared.js +9 -12
- package/dist/tools/evaluation/_shared.js.map +1 -1
- package/dist/tools/evaluation/bench.d.ts +29 -2
- package/dist/tools/evaluation/bench.d.ts.map +1 -1
- package/dist/tools/evaluation/bench.js +53 -9
- package/dist/tools/evaluation/bench.js.map +1 -1
- package/dist/tools/evaluation/compile.js +4 -4
- package/dist/tools/evaluation/compile.js.map +1 -1
- package/dist/tools/evaluation/eval.d.ts.map +1 -1
- package/dist/tools/evaluation/eval.js +12 -16
- package/dist/tools/evaluation/eval.js.map +1 -1
- package/dist/tools/evaluation/exec.d.ts +16 -0
- package/dist/tools/evaluation/exec.d.ts.map +1 -1
- package/dist/tools/evaluation/exec.js +38 -6
- package/dist/tools/evaluation/exec.js.map +1 -1
- package/dist/tools/evaluation/test-multiroot.d.ts +6 -0
- package/dist/tools/evaluation/test-multiroot.d.ts.map +1 -1
- package/dist/tools/evaluation/test-multiroot.js +35 -8
- package/dist/tools/evaluation/test-multiroot.js.map +1 -1
- package/dist/tools/evaluation/test.d.ts +45 -0
- package/dist/tools/evaluation/test.d.ts.map +1 -1
- package/dist/tools/evaluation/test.js +153 -32
- package/dist/tools/evaluation/test.js.map +1 -1
- package/dist/tools/helpers/coverage-gaps.d.ts +11 -3
- package/dist/tools/helpers/coverage-gaps.d.ts.map +1 -1
- package/dist/tools/helpers/coverage-gaps.js +7 -7
- package/dist/tools/helpers/coverage-gaps.js.map +1 -1
- package/dist/tools/helpers/describe-policy.d.ts.map +1 -1
- package/dist/tools/helpers/describe-policy.js +2 -2
- package/dist/tools/helpers/describe-policy.js.map +1 -1
- package/dist/tools/helpers/explain-decision.d.ts.map +1 -1
- package/dist/tools/helpers/explain-decision.js +3 -4
- package/dist/tools/helpers/explain-decision.js.map +1 -1
- package/dist/tools/helpers/explain-undefined.d.ts +9 -3
- package/dist/tools/helpers/explain-undefined.d.ts.map +1 -1
- package/dist/tools/helpers/explain-undefined.js +214 -73
- package/dist/tools/helpers/explain-undefined.js.map +1 -1
- package/dist/tools/helpers/fix.d.ts +11 -5
- package/dist/tools/helpers/fix.d.ts.map +1 -1
- package/dist/tools/helpers/fix.js +88 -45
- package/dist/tools/helpers/fix.js.map +1 -1
- package/dist/tools/helpers/generate-test-skeleton.d.ts.map +1 -1
- package/dist/tools/helpers/generate-test-skeleton.js +105 -21
- package/dist/tools/helpers/generate-test-skeleton.js.map +1 -1
- package/dist/tools/helpers/playground-share.d.ts +4 -2
- package/dist/tools/helpers/playground-share.d.ts.map +1 -1
- package/dist/tools/helpers/playground-share.js +13 -3
- package/dist/tools/helpers/playground-share.js.map +1 -1
- package/dist/tools/helpers/policy-diff.d.ts.map +1 -1
- package/dist/tools/helpers/policy-diff.js +3 -4
- package/dist/tools/helpers/policy-diff.js.map +1 -1
- package/dist/tools/helpers/security-audit.d.ts.map +1 -1
- package/dist/tools/helpers/security-audit.js +19 -19
- package/dist/tools/helpers/security-audit.js.map +1 -1
- package/dist/tools/helpers/verify.d.ts.map +1 -1
- package/dist/tools/helpers/verify.js +5 -1
- package/dist/tools/helpers/verify.js.map +1 -1
- package/dist/tools/meta/index.d.ts +1 -1
- package/dist/tools/server-management/_shared.d.ts +15 -4
- package/dist/tools/server-management/_shared.d.ts.map +1 -1
- package/dist/tools/server-management/_shared.js +86 -13
- package/dist/tools/server-management/_shared.js.map +1 -1
- package/dist/tools/server-management/data.d.ts.map +1 -1
- package/dist/tools/server-management/data.js +88 -23
- package/dist/tools/server-management/data.js.map +1 -1
- package/dist/tools/server-management/decisions.d.ts.map +1 -1
- package/dist/tools/server-management/decisions.js +16 -3
- package/dist/tools/server-management/decisions.js.map +1 -1
- package/dist/tools/server-management/policies.d.ts.map +1 -1
- package/dist/tools/server-management/policies.js +44 -7
- package/dist/tools/server-management/policies.js.map +1 -1
- package/dist/tools/server-management/status.d.ts.map +1 -1
- package/dist/tools/server-management/status.js +80 -13
- package/dist/tools/server-management/status.js.map +1 -1
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/conftest/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/conftest/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,MAAc;IACrE,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/pull.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/pull.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AA4B9C,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAuE5E"}
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* 0 -- pull succeeded
|
|
18
18
|
* non-0 -- network / auth error
|
|
19
19
|
*/
|
|
20
|
+
import { mkdir } from 'node:fs/promises';
|
|
21
|
+
import { dirname, resolve } from 'node:path';
|
|
20
22
|
import { z } from 'zod';
|
|
21
23
|
import { ConftestCli } from '../../lib/conftest-cli.js';
|
|
22
24
|
import { err, ok } from '../../lib/errors.js';
|
|
@@ -35,8 +37,12 @@ const ConftestPullInput = {
|
|
|
35
37
|
.optional()
|
|
36
38
|
.describe('Local directory where the pulled policies will be written. ' +
|
|
37
39
|
'Must be inside an allowed root (OPA_MCP_ALLOWED_PATHS). ' +
|
|
38
|
-
|
|
40
|
+
'Omitted, it falls back to `policy` in the working directory of the server process, the conftest convention, which must itself sit inside an allowed root. ' +
|
|
41
|
+
'The directory is emptied before the pull, so do not point it at one holding anything ' +
|
|
42
|
+
'you want to keep.'),
|
|
39
43
|
};
|
|
44
|
+
/** Where conftest looks when `--policy` is not given, as an absolute path. */
|
|
45
|
+
const DEFAULT_POLICY_DIR = resolve('policy');
|
|
40
46
|
export function registerConftestPull(server, config) {
|
|
41
47
|
const conftest = new ConftestCli(config);
|
|
42
48
|
server.registerTool('conftest_pull', {
|
|
@@ -59,24 +65,32 @@ export function registerConftestPull(server, config) {
|
|
|
59
65
|
}, async (input, { signal }) => {
|
|
60
66
|
return withToolEnvelope(config, async () => {
|
|
61
67
|
// ── Path validation ──────────────────────────────────────────────
|
|
62
|
-
// The
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
// The directory does not have to exist yet; conftest creates it. An
|
|
69
|
+
// omitted path means conftest's own default, which it resolves against
|
|
70
|
+
// the working directory. This tool writes files, so that default is
|
|
71
|
+
// checked against the allow-list too rather than escaping it by being
|
|
72
|
+
// implicit.
|
|
73
|
+
const v = validatePaths([input.policy ?? DEFAULT_POLICY_DIR], config);
|
|
74
|
+
if (!v.ok) {
|
|
75
|
+
if (input.policy !== undefined)
|
|
68
76
|
return v.error;
|
|
69
|
-
|
|
77
|
+
return err('PATH_NOT_ALLOWED', 'The conftest default policy directory is outside the allowed roots.', {
|
|
78
|
+
hint: 'Pass `policy` with a directory inside OPA_MCP_ALLOWED_PATHS.',
|
|
79
|
+
details: { defaultPolicyDir: DEFAULT_POLICY_DIR },
|
|
80
|
+
});
|
|
70
81
|
}
|
|
82
|
+
const policyDir = v.resolved[0];
|
|
83
|
+
// conftest runs from the parent, so the parent has to exist.
|
|
84
|
+
await mkdir(dirname(policyDir), { recursive: true });
|
|
71
85
|
// ── Run conftest pull ────────────────────────────────────────────
|
|
72
|
-
const result = await conftest.pull({ url: input.url, policy:
|
|
86
|
+
const result = await conftest.pull({ url: input.url, policy: policyDir }, signal);
|
|
73
87
|
const subprocessFailure = mapSubprocessFailure(result, 'conftest');
|
|
74
88
|
if (subprocessFailure)
|
|
75
89
|
return subprocessFailure;
|
|
76
90
|
if (result.exitCode === 0) {
|
|
77
91
|
return ok({
|
|
78
92
|
url: input.url,
|
|
79
|
-
policyDir
|
|
93
|
+
policyDir,
|
|
80
94
|
});
|
|
81
95
|
}
|
|
82
96
|
const detail = result.stderr.trim() || result.stdout.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../../src/tools/conftest/pull.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElG,MAAM,iBAAiB,GAAG;IACxB,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CACP,yCAAyC;QACvC,4CAA4C;QAC5C,qDAAqD;QACrD,uDAAuD;QACvD,gEAAgE,CACnE;IACH,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,6DAA6D;QAC3D,0DAA0D;QAC1D,
|
|
1
|
+
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../../src/tools/conftest/pull.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/push.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/push.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAyB9C,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAkE5E"}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* non-0 -- push error (auth failure, network error, etc.)
|
|
15
15
|
*/
|
|
16
16
|
import { z } from 'zod';
|
|
17
|
+
import { resolve } from 'node:path';
|
|
17
18
|
import { ConftestCli } from '../../lib/conftest-cli.js';
|
|
18
19
|
import { err, ok } from '../../lib/errors.js';
|
|
19
20
|
import { mapSubprocessFailure, validatePaths, withToolEnvelope } from '../../lib/tool-helpers.js';
|
|
@@ -30,8 +31,10 @@ const ConftestPushInput = {
|
|
|
30
31
|
.optional()
|
|
31
32
|
.describe('Path to the local directory containing Rego policies to push. ' +
|
|
32
33
|
'Must be inside an allowed root (OPA_MCP_ALLOWED_PATHS) and must exist. ' +
|
|
33
|
-
|
|
34
|
+
'Omitted, it falls back to `policy` in the working directory of the server process, the conftest convention, which must itself sit inside an allowed root.'),
|
|
34
35
|
};
|
|
36
|
+
/** Where conftest looks when `--policy` is not given, as an absolute path. */
|
|
37
|
+
const DEFAULT_POLICY_DIR = resolve('policy');
|
|
35
38
|
export function registerConftestPush(server, config) {
|
|
36
39
|
const conftest = new ConftestCli(config);
|
|
37
40
|
server.registerTool('conftest_push', {
|
|
@@ -51,21 +54,28 @@ export function registerConftestPush(server, config) {
|
|
|
51
54
|
}, async (input, { signal }) => {
|
|
52
55
|
return withToolEnvelope(config, async () => {
|
|
53
56
|
// ── Path validation ──────────────────────────────────────────────
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
// An omitted path means the conftest default, resolved against the
|
|
58
|
+
// working directory. This publishes whatever it finds there, so the
|
|
59
|
+
// default is checked against the allow-list like an explicit one.
|
|
60
|
+
const v = validatePaths([input.policy ?? DEFAULT_POLICY_DIR], config, { mustExist: true });
|
|
61
|
+
if (!v.ok) {
|
|
62
|
+
if (input.policy !== undefined)
|
|
57
63
|
return v.error;
|
|
58
|
-
|
|
64
|
+
return err('PATH_NOT_ALLOWED', 'The conftest default policy directory is outside the allowed roots.', {
|
|
65
|
+
hint: 'Pass `policy` with a directory inside OPA_MCP_ALLOWED_PATHS.',
|
|
66
|
+
details: { defaultPolicyDir: DEFAULT_POLICY_DIR },
|
|
67
|
+
});
|
|
59
68
|
}
|
|
69
|
+
const policyDir = v.resolved[0];
|
|
60
70
|
// ── Run conftest push ────────────────────────────────────────────
|
|
61
|
-
const result = await conftest.push({ repository: input.repository, policy:
|
|
71
|
+
const result = await conftest.push({ repository: input.repository, policy: policyDir }, signal);
|
|
62
72
|
const subprocessFailure = mapSubprocessFailure(result, 'conftest');
|
|
63
73
|
if (subprocessFailure)
|
|
64
74
|
return subprocessFailure;
|
|
65
75
|
if (result.exitCode === 0) {
|
|
66
76
|
return ok({
|
|
67
77
|
repository: input.repository,
|
|
68
|
-
policyDir
|
|
78
|
+
policyDir,
|
|
69
79
|
});
|
|
70
80
|
}
|
|
71
81
|
const detail = result.stderr.trim() || result.stdout.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../../src/tools/conftest/push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../../src/tools/conftest/push.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,19 +2,23 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import type { Config } from '../../config.js';
|
|
3
3
|
import { type ConftestFileResult } from '../../lib/conftest-cli.js';
|
|
4
4
|
export interface ConftestTestOutput {
|
|
5
|
-
/** `true` when no failures
|
|
5
|
+
/** `true` when conftest exited 0: no failures, and no warnings if `failOnWarn` was set. */
|
|
6
6
|
passed: boolean;
|
|
7
|
-
/**
|
|
7
|
+
/** One entry per (file, namespace) pair conftest evaluated, arrays always present. */
|
|
8
8
|
results: ConftestFileResult[];
|
|
9
9
|
summary: {
|
|
10
|
-
/**
|
|
10
|
+
/** Distinct files with no failure in any namespace. */
|
|
11
11
|
passed: number;
|
|
12
|
-
/**
|
|
12
|
+
/** Distinct files with at least one failure in any namespace. */
|
|
13
13
|
failed: number;
|
|
14
|
-
/**
|
|
14
|
+
/** Warning messages across all entries. */
|
|
15
15
|
warnings: number;
|
|
16
|
-
/**
|
|
16
|
+
/** Skipped-rule messages across all entries. */
|
|
17
17
|
skipped: number;
|
|
18
|
+
/** Rule evaluations that passed across all entries (conftest's `successes`). */
|
|
19
|
+
successes: number;
|
|
20
|
+
/** Failure messages across all entries. */
|
|
21
|
+
failures: number;
|
|
18
22
|
};
|
|
19
23
|
}
|
|
20
24
|
export declare function registerConftestTest(server: McpServer, config: Config): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/test.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,2BAA2B,CAAC;AAuFnC,MAAM,WAAW,kBAAkB;IACjC,2FAA2F;IAC3F,MAAM,EAAE,OAAO,CAAC;IAChB,sFAAsF;IACtF,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,EAAE;QACP,uDAAuD;QACvD,MAAM,EAAE,MAAM,CAAC;QACf,iEAAiE;QACjE,MAAM,EAAE,MAAM,CAAC;QACf,2CAA2C;QAC3C,QAAQ,EAAE,MAAM,CAAC;QACjB,gDAAgD;QAChD,OAAO,EAAE,MAAM,CAAC;QAChB,gFAAgF;QAChF,SAAS,EAAE,MAAM,CAAC;QAClB,2CAA2C;QAC3C,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAyH5E"}
|
|
@@ -11,13 +11,18 @@
|
|
|
11
11
|
* Exit code mapping:
|
|
12
12
|
* null -- conftest binary not found → CONFTEST_NOT_FOUND
|
|
13
13
|
* 0 -- all tests pass (ok: true, passed: true)
|
|
14
|
-
* 1 -- one or more failures (
|
|
15
|
-
*
|
|
14
|
+
* 1 -- one or more failures, or a command error (bad args, policy not
|
|
15
|
+
* found): the two are told apart by whether stdout holds results
|
|
16
|
+
* 2 -- failures together with warnings under --fail-on-warn
|
|
17
|
+
* Measured with conftest 0.69.0: a denial alone exits 1, a denial with
|
|
18
|
+
* --fail-on-warn exits 2, and both print the full result JSON. Any exit code
|
|
19
|
+
* with parseable results is an outcome, not a malfunction.
|
|
16
20
|
*/
|
|
17
21
|
import { z } from 'zod';
|
|
18
|
-
import { ConftestCli } from '../../lib/conftest-cli.js';
|
|
22
|
+
import { CONFTEST_PARSERS, ConftestCli, isConftestParser, parseConftestResults, } from '../../lib/conftest-cli.js';
|
|
19
23
|
import { err, ok } from '../../lib/errors.js';
|
|
20
|
-
import { mapSubprocessFailure,
|
|
24
|
+
import { mapSubprocessFailure, validatePaths, withToolEnvelope } from '../../lib/tool-helpers.js';
|
|
25
|
+
const PARSER_LIST = CONFTEST_PARSERS.join(', ');
|
|
21
26
|
const ConftestTestInput = {
|
|
22
27
|
files: z
|
|
23
28
|
.array(z.string())
|
|
@@ -31,19 +36,17 @@ const ConftestTestInput = {
|
|
|
31
36
|
.describe('Inline configuration content to evaluate (e.g. a Kubernetes manifest as a YAML string). ' +
|
|
32
37
|
'Mutually exclusive with `files`. Defaults to YAML format; set `inlineConfigParser` to override.'),
|
|
33
38
|
inlineConfigParser: z
|
|
34
|
-
.
|
|
39
|
+
.enum(CONFTEST_PARSERS)
|
|
35
40
|
.optional()
|
|
36
|
-
.describe(
|
|
37
|
-
'ini, xml, dotenv, cue, jsonnet, properties, edn, hocon, dockerfile. ' +
|
|
41
|
+
.describe(`Parser to use for \`inlineConfig\`. One of: ${PARSER_LIST}. Defaults to yaml. ` +
|
|
38
42
|
"Ignored when `files` is used (conftest infers the parser from each file's extension, " +
|
|
39
43
|
'unless `parser` is set).'),
|
|
40
44
|
parser: z
|
|
41
|
-
.
|
|
45
|
+
.enum(CONFTEST_PARSERS)
|
|
42
46
|
.optional()
|
|
43
47
|
.describe("Force a specific parser for all input `files` via conftest's global `--parser` flag, " +
|
|
44
48
|
'overriding extension-based detection. Useful for files whose extension does not match ' +
|
|
45
|
-
|
|
46
|
-
'hcl1, hcl2, ini, xml, dotenv, cue, jsonnet, properties, edn, hocon, dockerfile. ' +
|
|
49
|
+
`their format (e.g. parse a \`.tfstate\` file as \`json\`). One of: ${PARSER_LIST}. ` +
|
|
47
50
|
'For `inlineConfig`, prefer `inlineConfigParser`.'),
|
|
48
51
|
policy: z
|
|
49
52
|
.string()
|
|
@@ -93,13 +96,13 @@ export function registerConftestTest(server, config) {
|
|
|
93
96
|
'CONFTEST_NOT_FOUND otherwise. ' +
|
|
94
97
|
'Provide config via `files` (disk paths) or `inlineConfig` (inline string). ' +
|
|
95
98
|
'Provide policy via `policy` (disk path) or `inlinePolicy` (inline Rego source). ' +
|
|
96
|
-
"Omit `policy` and `inlinePolicy` to use conftest's default `./policy` directory."
|
|
99
|
+
"Omit `policy` and `inlinePolicy` to use conftest's default `./policy` directory. " +
|
|
100
|
+
'Policies are executed by conftest and can call OPA built-ins such as http.send.',
|
|
97
101
|
inputSchema: ConftestTestInput,
|
|
98
102
|
annotations: {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
openWorldHint: false,
|
|
103
|
+
// Runs Rego supplied by the caller; a policy can reach, and write to, a remote system through http.send.
|
|
104
|
+
readOnlyHint: false,
|
|
105
|
+
openWorldHint: true,
|
|
103
106
|
},
|
|
104
107
|
}, async (input, { signal }) => {
|
|
105
108
|
return withToolEnvelope(config, async () => {
|
|
@@ -113,6 +116,20 @@ export function registerConftestTest(server, config) {
|
|
|
113
116
|
if (input.policy !== undefined && input.inlinePolicy !== undefined) {
|
|
114
117
|
return err('INVALID_INPUT', '`policy` and `inlinePolicy` are mutually exclusive.');
|
|
115
118
|
}
|
|
119
|
+
// The schema restricts parser names to the closed set, and the
|
|
120
|
+
// check is repeated here because the name becomes part of a temp
|
|
121
|
+
// file path: this handler must never see free text there, whatever
|
|
122
|
+
// path it was reached by.
|
|
123
|
+
for (const [field, value] of [
|
|
124
|
+
['inlineConfigParser', input.inlineConfigParser],
|
|
125
|
+
['parser', input.parser],
|
|
126
|
+
]) {
|
|
127
|
+
if (value !== undefined && !isConftestParser(value)) {
|
|
128
|
+
return err('INVALID_INPUT', `\`${field}\` must be one of: ${PARSER_LIST}.`, {
|
|
129
|
+
details: { [field]: value },
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
116
133
|
// ── Path validation ──────────────────────────────────────────────
|
|
117
134
|
if (input.files?.length) {
|
|
118
135
|
const v = validatePaths(input.files, config, { mustExist: true });
|
|
@@ -150,47 +167,52 @@ export function registerConftestTest(server, config) {
|
|
|
150
167
|
const subprocessFailure = mapSubprocessFailure(result, 'conftest');
|
|
151
168
|
if (subprocessFailure)
|
|
152
169
|
return subprocessFailure;
|
|
153
|
-
// ──
|
|
154
|
-
// Exit 0
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return err('UNKNOWN_ERROR', 'conftest test produced no parseable JSON output.', {
|
|
160
|
-
details: { stderr: result.stderr.trim(), exitCode: result.exitCode },
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
const summary = buildSummary(parsed);
|
|
170
|
+
// ── Results on stdout: an outcome, whatever the exit code ────────
|
|
171
|
+
// Exit 0 is a pass; 1 and 2 carry failures (2 when --fail-on-warn
|
|
172
|
+
// adds warnings to them). Routing 2 to the error branch reported a
|
|
173
|
+
// real denial as a broken tool.
|
|
174
|
+
const results = parseConftestResults(result.stdout);
|
|
175
|
+
if (results !== null) {
|
|
164
176
|
return ok({
|
|
165
177
|
passed: result.exitCode === 0,
|
|
166
|
-
results
|
|
167
|
-
summary,
|
|
178
|
+
results,
|
|
179
|
+
summary: buildSummary(results),
|
|
168
180
|
});
|
|
169
181
|
}
|
|
170
|
-
// ──
|
|
182
|
+
// ── No results: a command-level error ────────────────────────────
|
|
171
183
|
// Examples: policy directory not found, malformed Rego syntax,
|
|
172
184
|
// unknown --parser value, etc.
|
|
173
185
|
const detail = result.stderr.trim() || result.stdout.trim();
|
|
174
|
-
return err('UNKNOWN_ERROR', `conftest test failed with exit code ${result.exitCode}: ${detail}`, { details: { exitCode: result.exitCode, stderr: result.stderr.trim() } });
|
|
186
|
+
return err('UNKNOWN_ERROR', `conftest test failed with exit code ${result.exitCode}: ${detail || 'no output'}`, { details: { exitCode: result.exitCode, stderr: result.stderr.trim() } });
|
|
175
187
|
});
|
|
176
188
|
});
|
|
177
189
|
}
|
|
178
190
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
179
191
|
function buildSummary(results) {
|
|
180
|
-
|
|
181
|
-
|
|
192
|
+
// conftest emits one entry per (file, namespace); with --all-namespaces a
|
|
193
|
+
// file appears once per namespace, so files are counted by name.
|
|
194
|
+
const failedFiles = new Set();
|
|
195
|
+
const allFiles = new Set();
|
|
182
196
|
let warnings = 0;
|
|
183
197
|
let skipped = 0;
|
|
198
|
+
let successes = 0;
|
|
199
|
+
let failures = 0;
|
|
184
200
|
for (const r of results) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
else {
|
|
189
|
-
passed++;
|
|
190
|
-
}
|
|
201
|
+
allFiles.add(r.filename);
|
|
202
|
+
if (r.failures.length > 0)
|
|
203
|
+
failedFiles.add(r.filename);
|
|
191
204
|
warnings += r.warnings.length;
|
|
192
205
|
skipped += r.skipped.length;
|
|
206
|
+
successes += r.successes;
|
|
207
|
+
failures += r.failures.length;
|
|
193
208
|
}
|
|
194
|
-
return {
|
|
209
|
+
return {
|
|
210
|
+
passed: allFiles.size - failedFiles.size,
|
|
211
|
+
failed: failedFiles.size,
|
|
212
|
+
warnings,
|
|
213
|
+
skipped,
|
|
214
|
+
successes,
|
|
215
|
+
failures,
|
|
216
|
+
};
|
|
195
217
|
}
|
|
196
218
|
//# sourceMappingURL=test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../../src/tools/conftest/test.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../../src/tools/conftest/test.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,18 +2,22 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import type { Config } from '../../config.js';
|
|
3
3
|
import { type ConftestFileResult } from '../../lib/conftest-cli.js';
|
|
4
4
|
export interface ConftestVerifyOutput {
|
|
5
|
-
/** `true` when
|
|
5
|
+
/** `true` when every `test_*` rule passed. */
|
|
6
6
|
passed: boolean;
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* One entry per test outcome as conftest reports them: a test file
|
|
9
|
+
* produces one entry per passing rule (`successes: 1`) and one per
|
|
10
|
+
* failing rule (`failures: [{msg}]`), with `namespace` empty.
|
|
11
|
+
*/
|
|
8
12
|
results: ConftestFileResult[];
|
|
9
13
|
summary: {
|
|
10
|
-
/**
|
|
14
|
+
/** Distinct test files with no failing rule. */
|
|
11
15
|
passed: number;
|
|
12
|
-
/**
|
|
16
|
+
/** Distinct test files with at least one failing rule. */
|
|
13
17
|
failed: number;
|
|
14
|
-
/**
|
|
18
|
+
/** Test rules that passed, across all files. */
|
|
15
19
|
totalPassed: number;
|
|
16
|
-
/**
|
|
20
|
+
/** Test rules that failed, across all files. */
|
|
17
21
|
totalFailed: number;
|
|
18
22
|
};
|
|
19
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/verify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/tools/conftest/verify.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,2BAA2B,CAAC;AAsBnC,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,EAAE;QACP,gDAAgD;QAChD,MAAM,EAAE,MAAM,CAAC;QACf,0DAA0D;QAC1D,MAAM,EAAE,MAAM,CAAC;QACf,gDAAgD;QAChD,WAAW,EAAE,MAAM,CAAC;QACpB,gDAAgD;QAChD,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAgF9E"}
|
|
@@ -7,16 +7,19 @@
|
|
|
7
7
|
* the policy directory. Use this to confirm that the policies themselves
|
|
8
8
|
* are correct before deploying them.
|
|
9
9
|
*
|
|
10
|
-
* Exit code mapping
|
|
10
|
+
* Exit code mapping:
|
|
11
11
|
* null -- binary not found → CONFTEST_NOT_FOUND
|
|
12
12
|
* 0 -- all tests pass
|
|
13
|
-
* 1 --
|
|
14
|
-
*
|
|
13
|
+
* 1 -- test failures when stdout holds results, a command error when it
|
|
14
|
+
* does not
|
|
15
|
+
* `conftest verify` has no --fail-on-warn, so the exit code 2 that
|
|
16
|
+
* conftest_test handles does not occur here; the results-on-stdout rule is
|
|
17
|
+
* shared so a command error reaches the caller with conftest's own message.
|
|
15
18
|
*/
|
|
16
19
|
import { z } from 'zod';
|
|
17
|
-
import { ConftestCli } from '../../lib/conftest-cli.js';
|
|
20
|
+
import { ConftestCli, parseConftestResults, } from '../../lib/conftest-cli.js';
|
|
18
21
|
import { err, ok } from '../../lib/errors.js';
|
|
19
|
-
import { mapSubprocessFailure,
|
|
22
|
+
import { mapSubprocessFailure, validatePaths, withToolEnvelope } from '../../lib/tool-helpers.js';
|
|
20
23
|
const ConftestVerifyInput = {
|
|
21
24
|
policy: z
|
|
22
25
|
.string()
|
|
@@ -24,10 +27,7 @@ const ConftestVerifyInput = {
|
|
|
24
27
|
.describe('Path to the directory containing both the Rego policies and the `*_test.rego` test files. ' +
|
|
25
28
|
'Must be inside an allowed root (OPA_MCP_ALLOWED_PATHS). ' +
|
|
26
29
|
"Omit to use conftest's default `./policy` directory."),
|
|
27
|
-
namespace: z
|
|
28
|
-
.string()
|
|
29
|
-
.optional()
|
|
30
|
-
.describe('Namespace to verify. Defaults to `main`. Omit to verify all namespaces.'),
|
|
30
|
+
namespace: z.string().optional().describe('Namespace to verify. Omit to verify all namespaces.'),
|
|
31
31
|
data: z
|
|
32
32
|
.array(z.string())
|
|
33
33
|
.optional()
|
|
@@ -39,14 +39,14 @@ export function registerConftestVerify(server, config) {
|
|
|
39
39
|
title: 'Conftest verify',
|
|
40
40
|
description: 'Run the `test_*` rules inside `*_test.rego` files within a conftest policy directory, ' +
|
|
41
41
|
'verifying that the policies themselves are correct. Equivalent to `opa test` but using ' +
|
|
42
|
-
"conftest's policy-loading machinery. Returns per-file pass/fail results
|
|
42
|
+
"conftest's policy-loading machinery. Returns per-file pass/fail results, and " +
|
|
43
|
+
'NO_TESTS_FOUND when the directory holds no test rules. ' +
|
|
43
44
|
'Requires `conftest` on PATH or `CONFTEST_BINARY` set; returns CONFTEST_NOT_FOUND otherwise.',
|
|
44
45
|
inputSchema: ConftestVerifyInput,
|
|
45
46
|
annotations: {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
openWorldHint: false,
|
|
47
|
+
// Runs Rego supplied by the caller; a policy can reach, and write to, a remote system through http.send.
|
|
48
|
+
readOnlyHint: false,
|
|
49
|
+
openWorldHint: true,
|
|
50
50
|
},
|
|
51
51
|
}, async (input, { signal }) => {
|
|
52
52
|
return withToolEnvelope(config, async () => {
|
|
@@ -72,41 +72,49 @@ export function registerConftestVerify(server, config) {
|
|
|
72
72
|
const subprocessFailure = mapSubprocessFailure(result, 'conftest');
|
|
73
73
|
if (subprocessFailure)
|
|
74
74
|
return subprocessFailure;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
// Results on stdout are an outcome whatever the exit code; see
|
|
76
|
+
// conftest_test for the measured codes.
|
|
77
|
+
const results = parseConftestResults(result.stdout);
|
|
78
|
+
if (results !== null) {
|
|
79
|
+
// conftest prints `null` and exits 0 when it finds no test rules.
|
|
80
|
+
// A clean pass over nothing is not a pass.
|
|
81
|
+
if (results.length === 0) {
|
|
82
|
+
return err('NO_TESTS_FOUND', 'conftest verify found no test rules in the policy directory.', {
|
|
83
|
+
hint: 'Tests live in *_test.rego files inside the policy directory, with rules named test_*.',
|
|
80
84
|
});
|
|
81
85
|
}
|
|
82
|
-
const summary = buildVerifySummary(parsed);
|
|
83
86
|
return ok({
|
|
84
87
|
passed: result.exitCode === 0,
|
|
85
|
-
results
|
|
86
|
-
summary,
|
|
88
|
+
results,
|
|
89
|
+
summary: buildVerifySummary(results),
|
|
87
90
|
});
|
|
88
91
|
}
|
|
89
92
|
const detail = result.stderr.trim() || result.stdout.trim();
|
|
90
|
-
return err('UNKNOWN_ERROR', `conftest verify failed with exit code ${result.exitCode}: ${detail}`, { details: { exitCode: result.exitCode, stderr: result.stderr.trim() } });
|
|
93
|
+
return err('UNKNOWN_ERROR', `conftest verify failed with exit code ${result.exitCode}: ${detail || 'no output'}`, { details: { exitCode: result.exitCode, stderr: result.stderr.trim() } });
|
|
91
94
|
});
|
|
92
95
|
});
|
|
93
96
|
}
|
|
94
97
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
95
98
|
function buildVerifySummary(results) {
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
// conftest verify reports one entry per test rule, all carrying the test
|
|
100
|
+
// file's name, so a file with one pass and one failure arrives as two
|
|
101
|
+
// entries. Files are counted by name, rules by entry.
|
|
102
|
+
const allFiles = new Set();
|
|
103
|
+
const failedFiles = new Set();
|
|
98
104
|
let totalPassed = 0;
|
|
99
105
|
let totalFailed = 0;
|
|
100
106
|
for (const r of results) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
else {
|
|
105
|
-
passed++;
|
|
106
|
-
}
|
|
107
|
+
allFiles.add(r.filename);
|
|
108
|
+
if (r.failures.length > 0)
|
|
109
|
+
failedFiles.add(r.filename);
|
|
107
110
|
totalPassed += r.successes;
|
|
108
111
|
totalFailed += r.failures.length;
|
|
109
112
|
}
|
|
110
|
-
return {
|
|
113
|
+
return {
|
|
114
|
+
passed: allFiles.size - failedFiles.size,
|
|
115
|
+
failed: failedFiles.size,
|
|
116
|
+
totalPassed,
|
|
117
|
+
totalFailed,
|
|
118
|
+
};
|
|
111
119
|
}
|
|
112
120
|
//# sourceMappingURL=verify.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/tools/conftest/verify.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/tools/conftest/verify.ts"],"names":[],"mappings":"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"}
|