@stsepelin/checktrail 0.1.0-alpha.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.
- package/CONTRIBUTING.md +42 -0
- package/LICENSE +21 -0
- package/README.md +355 -0
- package/SECURITY.md +46 -0
- package/dist/src/actionlint-evidence.d.ts +2 -0
- package/dist/src/actionlint-evidence.js +166 -0
- package/dist/src/actionlint-inputs.d.ts +5 -0
- package/dist/src/actionlint-inputs.js +123 -0
- package/dist/src/actionlint-runner.d.ts +1 -0
- package/dist/src/actionlint-runner.js +122 -0
- package/dist/src/actionlint.d.ts +19 -0
- package/dist/src/actionlint.js +80 -0
- package/dist/src/adapters.d.ts +49 -0
- package/dist/src/adapters.js +430 -0
- package/dist/src/architecture.d.ts +107 -0
- package/dist/src/architecture.js +230 -0
- package/dist/src/clang-evidence.d.ts +2 -0
- package/dist/src/clang-evidence.js +194 -0
- package/dist/src/clang-protocol.d.ts +3 -0
- package/dist/src/clang-protocol.js +25 -0
- package/dist/src/clang-runner.d.ts +1 -0
- package/dist/src/clang-runner.js +159 -0
- package/dist/src/clang.d.ts +44 -0
- package/dist/src/clang.js +197 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +338 -0
- package/dist/src/config.d.ts +33 -0
- package/dist/src/config.js +140 -0
- package/dist/src/contract-schema.d.ts +85 -0
- package/dist/src/contract-schema.js +56 -0
- package/dist/src/contract-worker.d.ts +1 -0
- package/dist/src/contract-worker.js +123 -0
- package/dist/src/contracts.d.ts +22 -0
- package/dist/src/contracts.js +123 -0
- package/dist/src/django-evidence.d.ts +2 -0
- package/dist/src/django-evidence.js +100 -0
- package/dist/src/django-runner.d.ts +1 -0
- package/dist/src/django-runner.js +80 -0
- package/dist/src/django.d.ts +9 -0
- package/dist/src/django.js +50 -0
- package/dist/src/dotnet-compiler.d.ts +1 -0
- package/dist/src/dotnet-compiler.js +87 -0
- package/dist/src/dotnet-evidence.d.ts +2 -0
- package/dist/src/dotnet-evidence.js +127 -0
- package/dist/src/dotnet-runner.d.ts +1 -0
- package/dist/src/dotnet-runner.js +167 -0
- package/dist/src/dotnet.d.ts +65 -0
- package/dist/src/dotnet.js +120 -0
- package/dist/src/engine.d.ts +19 -0
- package/dist/src/engine.js +239 -0
- package/dist/src/environment.d.ts +6 -0
- package/dist/src/environment.js +36 -0
- package/dist/src/eslint-evidence.d.ts +2 -0
- package/dist/src/eslint-evidence.js +98 -0
- package/dist/src/eslint-runner.d.ts +1 -0
- package/dist/src/eslint-runner.js +61 -0
- package/dist/src/eslint.d.ts +2 -0
- package/dist/src/eslint.js +40 -0
- package/dist/src/evidence.d.ts +2 -0
- package/dist/src/evidence.js +313 -0
- package/dist/src/external-adapter.d.ts +164 -0
- package/dist/src/external-adapter.js +265 -0
- package/dist/src/external-evidence.d.ts +2 -0
- package/dist/src/external-evidence.js +127 -0
- package/dist/src/external-runner.d.ts +1 -0
- package/dist/src/external-runner.js +122 -0
- package/dist/src/fastapi-evidence.d.ts +2 -0
- package/dist/src/fastapi-evidence.js +126 -0
- package/dist/src/fastapi-runner.d.ts +1 -0
- package/dist/src/fastapi-runner.js +84 -0
- package/dist/src/fastapi.d.ts +10 -0
- package/dist/src/fastapi.js +52 -0
- package/dist/src/fetch-pack.d.ts +16 -0
- package/dist/src/fetch-pack.js +154 -0
- package/dist/src/finding-policy-schema.d.ts +146 -0
- package/dist/src/finding-policy-schema.js +70 -0
- package/dist/src/finding-policy.d.ts +62 -0
- package/dist/src/finding-policy.js +206 -0
- package/dist/src/git-selection.d.ts +3 -0
- package/dist/src/git-selection.js +229 -0
- package/dist/src/go-directives.d.ts +1 -0
- package/dist/src/go-directives.js +32 -0
- package/dist/src/go-scope.d.ts +11 -0
- package/dist/src/go-scope.js +122 -0
- package/dist/src/golangci-evidence.d.ts +2 -0
- package/dist/src/golangci-evidence.js +92 -0
- package/dist/src/golangci-runner.d.ts +1 -0
- package/dist/src/golangci-runner.js +124 -0
- package/dist/src/golangci.d.ts +2 -0
- package/dist/src/golangci.js +35 -0
- package/dist/src/guidance.d.ts +98 -0
- package/dist/src/guidance.js +247 -0
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.js +16 -0
- package/dist/src/inventory.d.ts +4 -0
- package/dist/src/inventory.js +94 -0
- package/dist/src/java-compiler.d.ts +1 -0
- package/dist/src/java-compiler.js +110 -0
- package/dist/src/java-evidence.d.ts +2 -0
- package/dist/src/java-evidence.js +114 -0
- package/dist/src/java-runner.d.ts +1 -0
- package/dist/src/java-runner.js +79 -0
- package/dist/src/java.d.ts +25 -0
- package/dist/src/java.js +102 -0
- package/dist/src/jest-evidence.d.ts +2 -0
- package/dist/src/jest-evidence.js +117 -0
- package/dist/src/jest-runner.d.ts +1 -0
- package/dist/src/jest-runner.js +46 -0
- package/dist/src/jest.d.ts +2 -0
- package/dist/src/jest.js +36 -0
- package/dist/src/junit.d.ts +18 -0
- package/dist/src/junit.js +157 -0
- package/dist/src/laravel-evidence.d.ts +2 -0
- package/dist/src/laravel-evidence.js +175 -0
- package/dist/src/laravel-runner.d.ts +1 -0
- package/dist/src/laravel-runner.js +168 -0
- package/dist/src/laravel.d.ts +8 -0
- package/dist/src/laravel.js +50 -0
- package/dist/src/local-tool.d.ts +1 -0
- package/dist/src/local-tool.js +19 -0
- package/dist/src/mcp.d.ts +14 -0
- package/dist/src/mcp.js +362 -0
- package/dist/src/mutation.d.ts +118 -0
- package/dist/src/mutation.js +370 -0
- package/dist/src/mypy-evidence.d.ts +2 -0
- package/dist/src/mypy-evidence.js +63 -0
- package/dist/src/mypy.d.ts +2 -0
- package/dist/src/mypy.js +59 -0
- package/dist/src/node-reporter.d.ts +1 -0
- package/dist/src/node-reporter.js +28 -0
- package/dist/src/nuxt-evidence.d.ts +2 -0
- package/dist/src/nuxt-evidence.js +160 -0
- package/dist/src/nuxt-protocol.d.ts +52 -0
- package/dist/src/nuxt-protocol.js +29 -0
- package/dist/src/nuxt-runner.d.ts +1 -0
- package/dist/src/nuxt-runner.js +165 -0
- package/dist/src/nuxt.d.ts +24 -0
- package/dist/src/nuxt.js +105 -0
- package/dist/src/output.d.ts +3 -0
- package/dist/src/output.js +48 -0
- package/dist/src/phpstan-evidence.d.ts +2 -0
- package/dist/src/phpstan-evidence.js +81 -0
- package/dist/src/phpstan.d.ts +2 -0
- package/dist/src/phpstan.js +51 -0
- package/dist/src/phpunit-evidence.d.ts +2 -0
- package/dist/src/phpunit-evidence.js +53 -0
- package/dist/src/phpunit.d.ts +2 -0
- package/dist/src/phpunit.js +58 -0
- package/dist/src/pint-evidence.d.ts +2 -0
- package/dist/src/pint-evidence.js +79 -0
- package/dist/src/pint-runner.d.ts +1 -0
- package/dist/src/pint-runner.js +53 -0
- package/dist/src/pint.d.ts +2 -0
- package/dist/src/pint.js +37 -0
- package/dist/src/playwright-evidence.d.ts +2 -0
- package/dist/src/playwright-evidence.js +127 -0
- package/dist/src/playwright-reporter.d.ts +10 -0
- package/dist/src/playwright-reporter.js +37 -0
- package/dist/src/playwright-runner.d.ts +1 -0
- package/dist/src/playwright-runner.js +61 -0
- package/dist/src/playwright.d.ts +2 -0
- package/dist/src/playwright.js +35 -0
- package/dist/src/policy-pack.d.ts +21 -0
- package/dist/src/policy-pack.js +41 -0
- package/dist/src/pytest-evidence.d.ts +2 -0
- package/dist/src/pytest-evidence.js +116 -0
- package/dist/src/pytest-runner.d.ts +1 -0
- package/dist/src/pytest-runner.js +48 -0
- package/dist/src/pytest.d.ts +2 -0
- package/dist/src/pytest.js +25 -0
- package/dist/src/report-validation.d.ts +129 -0
- package/dist/src/report-validation.js +27 -0
- package/dist/src/review.d.ts +270 -0
- package/dist/src/review.js +349 -0
- package/dist/src/ruby.d.ts +2 -0
- package/dist/src/ruby.js +25 -0
- package/dist/src/ruff-evidence.d.ts +2 -0
- package/dist/src/ruff-evidence.js +99 -0
- package/dist/src/ruff.d.ts +2 -0
- package/dist/src/ruff.js +40 -0
- package/dist/src/runner.d.ts +8 -0
- package/dist/src/runner.js +117 -0
- package/dist/src/runtime-inventory.d.ts +112 -0
- package/dist/src/runtime-inventory.js +200 -0
- package/dist/src/rust-dep-info.d.ts +1 -0
- package/dist/src/rust-dep-info.js +46 -0
- package/dist/src/rust-evidence.d.ts +2 -0
- package/dist/src/rust-evidence.js +157 -0
- package/dist/src/rust-runner.d.ts +1 -0
- package/dist/src/rust-runner.js +161 -0
- package/dist/src/rust.d.ts +7 -0
- package/dist/src/rust.js +39 -0
- package/dist/src/sarif.d.ts +86 -0
- package/dist/src/sarif.js +113 -0
- package/dist/src/schemas.d.ts +393 -0
- package/dist/src/schemas.js +222 -0
- package/dist/src/staticcheck-evidence.d.ts +2 -0
- package/dist/src/staticcheck-evidence.js +75 -0
- package/dist/src/swift.d.ts +2 -0
- package/dist/src/swift.js +20 -0
- package/dist/src/task-store.d.ts +37 -0
- package/dist/src/task-store.js +349 -0
- package/dist/src/tool-versions.d.ts +3 -0
- package/dist/src/tool-versions.js +260 -0
- package/dist/src/types.d.ts +157 -0
- package/dist/src/types.js +37 -0
- package/dist/src/typescript-build-evidence.d.ts +2 -0
- package/dist/src/typescript-build-evidence.js +86 -0
- package/dist/src/typescript-build-runner.d.ts +1 -0
- package/dist/src/typescript-build-runner.js +132 -0
- package/dist/src/typescript-build.d.ts +2 -0
- package/dist/src/typescript-build.js +41 -0
- package/dist/src/typescript.d.ts +2 -0
- package/dist/src/typescript.js +54 -0
- package/dist/src/validation-task-worker.d.ts +1 -0
- package/dist/src/validation-task-worker.js +205 -0
- package/dist/src/validation-tasks-protocol.d.ts +69 -0
- package/dist/src/validation-tasks-protocol.js +57 -0
- package/dist/src/validation-tasks.d.ts +11 -0
- package/dist/src/validation-tasks.js +144 -0
- package/dist/src/vitest-evidence.d.ts +2 -0
- package/dist/src/vitest-evidence.js +112 -0
- package/dist/src/vitest-runner.d.ts +1 -0
- package/dist/src/vitest-runner.js +48 -0
- package/dist/src/vitest.d.ts +2 -0
- package/dist/src/vitest.js +36 -0
- package/dist/src/vue-router-capture.d.ts +42 -0
- package/dist/src/vue-router-capture.js +87 -0
- package/dist/src/vue-router-evidence.d.ts +2 -0
- package/dist/src/vue-router-evidence.js +126 -0
- package/dist/src/vue-router-protocol.d.ts +63 -0
- package/dist/src/vue-router-protocol.js +44 -0
- package/dist/src/vue-router-runner.d.ts +1 -0
- package/dist/src/vue-router-runner.js +88 -0
- package/dist/src/vue-router.d.ts +23 -0
- package/dist/src/vue-router.js +108 -0
- package/dist/src/vue-tsc-runner.d.ts +1 -0
- package/dist/src/vue-tsc-runner.js +24 -0
- package/dist/src/workspace.d.ts +7 -0
- package/dist/src/workspace.js +53 -0
- package/docs/ACCEPTANCE.md +56 -0
- package/docs/ACTIONLINT.md +112 -0
- package/docs/ARCHITECTURE-POLICY.md +82 -0
- package/docs/ARCHITECTURE.md +122 -0
- package/docs/CLANG.md +113 -0
- package/docs/CLIENTS.md +109 -0
- package/docs/CONTRACTS.md +73 -0
- package/docs/DEPENDENCIES.md +42 -0
- package/docs/DJANGO.md +70 -0
- package/docs/DOTNET.md +114 -0
- package/docs/ENVIRONMENTS.md +52 -0
- package/docs/ESLINT.md +68 -0
- package/docs/EVALUATION.md +124 -0
- package/docs/EXECUTION.md +250 -0
- package/docs/EXTERNAL-ADAPTERS.md +170 -0
- package/docs/EXTERNAL-EVALUATION.md +155 -0
- package/docs/EXTERNAL-RUFF-EVALUATION.md +85 -0
- package/docs/FASTAPI.md +73 -0
- package/docs/FINDING-POLICY.md +67 -0
- package/docs/GO-RACE.md +19 -0
- package/docs/GO-SCOPE.md +63 -0
- package/docs/GOLANGCI-LINT.md +64 -0
- package/docs/GUIDANCE.md +46 -0
- package/docs/IMPACT-MEASUREMENT.md +97 -0
- package/docs/INSTALLATION.md +102 -0
- package/docs/JAVA.md +79 -0
- package/docs/JEST.md +36 -0
- package/docs/JUNIT.md +31 -0
- package/docs/LANGUAGES.md +113 -0
- package/docs/LARAVEL.md +111 -0
- package/docs/MCP-COMPATIBILITY.md +68 -0
- package/docs/MUTATIONS.md +93 -0
- package/docs/MYPY.md +37 -0
- package/docs/NATIVE-CI.md +96 -0
- package/docs/NUXT.md +123 -0
- package/docs/PACK-DISTRIBUTION.md +98 -0
- package/docs/PERFORMANCE.md +71 -0
- package/docs/PEST.md +36 -0
- package/docs/PHPSTAN.md +48 -0
- package/docs/PHPUNIT.md +32 -0
- package/docs/PINT.md +41 -0
- package/docs/PLAN.md +265 -0
- package/docs/PLAYWRIGHT.md +73 -0
- package/docs/POLICY-PACKS.md +106 -0
- package/docs/PRIOR-WORKFLOW-EVALUATION.md +116 -0
- package/docs/PUBLICATION.md +28 -0
- package/docs/PYTEST.md +51 -0
- package/docs/RELEASE.md +115 -0
- package/docs/RENAMING.md +55 -0
- package/docs/REVIEW-EXCHANGE.md +136 -0
- package/docs/RUBY.md +50 -0
- package/docs/RUFF.md +39 -0
- package/docs/RUNTIME-INVENTORY.md +56 -0
- package/docs/RUST.md +74 -0
- package/docs/SARIF.md +64 -0
- package/docs/STATUS.md +530 -0
- package/docs/SWIFT.md +48 -0
- package/docs/TASK-STORAGE.md +141 -0
- package/docs/TOOL-IDENTITY.md +30 -0
- package/docs/TYPESCRIPT-BUILD.md +55 -0
- package/docs/VALIDATION-TASKS.md +119 -0
- package/docs/VITEST.md +36 -0
- package/docs/VUE-ROUTER.md +130 -0
- package/docs/VUE-TSC.md +26 -0
- package/docs/WORKSPACES.md +81 -0
- package/docs/licenses/nodable-entities-3.0.0.txt +21 -0
- package/docs/measurements/client-claude-before-schema-fix-darwin-arm64-node26.json +60 -0
- package/docs/measurements/client-claude-darwin-arm64-node26.json +55 -0
- package/docs/measurements/client-codex-darwin-arm64-node26.json +175 -0
- package/docs/measurements/evaluation-corpus-repo-verifier.json +332 -0
- package/docs/measurements/evaluation-darwin-arm64-node26.json +1236 -0
- package/docs/measurements/evaluation-linux-arm64-node22.json +1236 -0
- package/docs/measurements/external-eslint-darwin-arm64-node26.json +11866 -0
- package/docs/measurements/external-eslint-linux-arm64-node22.json +11866 -0
- package/docs/measurements/external-eslint-preservation.json +1527 -0
- package/docs/measurements/external-ruff-darwin-arm64-node26.json +1031 -0
- package/docs/measurements/external-ruff-linux-arm64-node22.json +1031 -0
- package/docs/measurements/hosted-ci-52ba415.json +1005 -0
- package/docs/measurements/impact-darwin-arm64-node26.json +6685 -0
- package/docs/measurements/impact-linux-arm64-node22.json +6690 -0
- package/docs/measurements/performance-darwin-arm64-node26.json +845 -0
- package/docs/measurements/performance-linux-arm64-node22.json +845 -0
- package/docs/measurements/required-native-profiles.json +500 -0
- package/package.json +72 -0
- package/packs/actionlint.json +8 -0
- package/packs/cpp.json +8 -0
- package/packs/dotnet.json +8 -0
- package/packs/go.json +7 -0
- package/packs/java.json +8 -0
- package/packs/javascript-node.json +7 -0
- package/packs/nuxt.json +7 -0
- package/packs/php-pest.json +7 -0
- package/packs/php-phpunit.json +7 -0
- package/packs/python-pytest.json +7 -0
- package/packs/ruby.json +7 -0
- package/packs/rust.json +7 -0
- package/packs/swift.json +7 -0
- package/packs/vue-router.json +7 -0
- package/packs/vue.json +11 -0
- package/schemas/actionlint-config.schema.json +19 -0
- package/schemas/architecture-policy.schema.json +51 -0
- package/schemas/architecture-report.schema.json +123 -0
- package/schemas/architecture-summary.schema.json +82 -0
- package/schemas/clang-database.schema.json +23 -0
- package/schemas/config.schema.json +69 -0
- package/schemas/contract-bundle.schema.json +78 -0
- package/schemas/contract-report.schema.json +114 -0
- package/schemas/contract-summary.schema.json +72 -0
- package/schemas/dependency-graph.schema.json +65 -0
- package/schemas/django-config.schema.json +16 -0
- package/schemas/dotnet-config.schema.json +60 -0
- package/schemas/external-manifest.schema.json +97 -0
- package/schemas/external-reference.schema.json +10 -0
- package/schemas/external-request.schema.json +56 -0
- package/schemas/external-result.schema.json +111 -0
- package/schemas/fastapi-config.schema.json +27 -0
- package/schemas/finding-baseline.schema.json +92 -0
- package/schemas/finding-comparison-summary.schema.json +95 -0
- package/schemas/finding-comparison.schema.json +121 -0
- package/schemas/guidance-context.schema.json +34 -0
- package/schemas/guidance-report.schema.json +176 -0
- package/schemas/guidance-summary.schema.json +68 -0
- package/schemas/java-config.schema.json +24 -0
- package/schemas/junit.schema.json +69 -0
- package/schemas/laravel-config.schema.json +11 -0
- package/schemas/mutation-recipe.schema.json +31 -0
- package/schemas/mutation-report.schema.json +238 -0
- package/schemas/mutation-summary.schema.json +98 -0
- package/schemas/nuxt-config.schema.json +51 -0
- package/schemas/plan-summary.schema.json +63 -0
- package/schemas/plan.schema.json +244 -0
- package/schemas/policy-pack.schema.json +41 -0
- package/schemas/report-summary.schema.json +100 -0
- package/schemas/report.schema.json +463 -0
- package/schemas/review-assessment.schema.json +133 -0
- package/schemas/review-context-summary.schema.json +31 -0
- package/schemas/review-context.schema.json +254 -0
- package/schemas/review-receipt-summary.schema.json +104 -0
- package/schemas/review-receipt.schema.json +271 -0
- package/schemas/review-selection.schema.json +30 -0
- package/schemas/runtime-comparison-summary.schema.json +68 -0
- package/schemas/runtime-comparison.schema.json +127 -0
- package/schemas/runtime-inventory.schema.json +99 -0
- package/schemas/vue-router-config.schema.json +67 -0
- package/server.json +47 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { access, realpath, stat } from "node:fs/promises";
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { readProjectFile, withinRoot } from "./inventory.js";
|
|
7
|
+
const text = z
|
|
8
|
+
.string()
|
|
9
|
+
.min(1)
|
|
10
|
+
.max(8192)
|
|
11
|
+
.refine((value) => !value.includes("\0"));
|
|
12
|
+
export const clangDatabaseSchema = z
|
|
13
|
+
.array(z.strictObject({
|
|
14
|
+
directory: text,
|
|
15
|
+
file: text,
|
|
16
|
+
arguments: z.array(text).min(2).max(256).optional(),
|
|
17
|
+
command: text.optional(),
|
|
18
|
+
output: text.optional(),
|
|
19
|
+
}))
|
|
20
|
+
.min(1)
|
|
21
|
+
.max(64);
|
|
22
|
+
export const clangUnitSchema = z.strictObject({
|
|
23
|
+
compiler: z.enum(["clang", "clang++"]),
|
|
24
|
+
cwd: z.string(),
|
|
25
|
+
file: z.string(),
|
|
26
|
+
input: z.string().min(1),
|
|
27
|
+
args: z.array(z.string()),
|
|
28
|
+
});
|
|
29
|
+
export const clangInvocationSchema = z.strictObject({
|
|
30
|
+
units: z.array(clangUnitSchema).min(1).max(64),
|
|
31
|
+
scope: z.array(z.string()).min(1).max(20_000),
|
|
32
|
+
});
|
|
33
|
+
export const clangEnvironment = {
|
|
34
|
+
// Clang treats a leading # as a quiet, empty override list.
|
|
35
|
+
CCC_OVERRIDE_OPTIONS: "#",
|
|
36
|
+
CPATH: "",
|
|
37
|
+
C_INCLUDE_PATH: "",
|
|
38
|
+
CPLUS_INCLUDE_PATH: "",
|
|
39
|
+
OBJC_INCLUDE_PATH: "",
|
|
40
|
+
CLANG_CONFIG_FILE_USER_DIR: "",
|
|
41
|
+
CLANG_CONFIG_FILE_SYSTEM_DIR: "",
|
|
42
|
+
};
|
|
43
|
+
const sourceExtension = /\.(?:c|cc|cpp|cxx|C|c\+\+)$/;
|
|
44
|
+
const inventoriedExtension = /\.(?:c|cc|cpp|cxx|C|c\+\+|h|hh|hpp|hxx|h\+\+|inc|ipp|tpp|ixx|cppm)$/;
|
|
45
|
+
export async function clangExecutableMatches(name, declared) {
|
|
46
|
+
if (declared === name)
|
|
47
|
+
return true;
|
|
48
|
+
if (!path.isAbsolute(declared) || path.basename(declared) !== name)
|
|
49
|
+
return false;
|
|
50
|
+
for (const directory of (process.env.PATH ?? "").split(path.delimiter)) {
|
|
51
|
+
const candidate = path.resolve(directory, name);
|
|
52
|
+
try {
|
|
53
|
+
await access(candidate, constants.X_OK);
|
|
54
|
+
return (await realpath(candidate)) === (await realpath(declared));
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
/* Keep searching PATH until its first executable is found. */
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
async function databaseUnits(source, project) {
|
|
63
|
+
const database = clangDatabaseSchema.parse(JSON.parse(await readProjectFile(source.root, path.posix.join(project.path, "compile_commands.json"))));
|
|
64
|
+
const projectRoot = await withinRoot(source.root, project.path);
|
|
65
|
+
const units = [];
|
|
66
|
+
for (const entry of database) {
|
|
67
|
+
if (!entry.arguments)
|
|
68
|
+
throw new Error("Shell-string compilation databases require an arguments-array export");
|
|
69
|
+
const cwd = await withinRoot(source.root, path.relative(source.root, path.resolve(projectRoot, entry.directory)));
|
|
70
|
+
if (!(await stat(cwd)).isDirectory())
|
|
71
|
+
throw new Error("Compilation directory must exist");
|
|
72
|
+
const absolute = await withinRoot(source.root, path.relative(source.root, path.resolve(cwd, entry.file)));
|
|
73
|
+
const file = path.relative(projectRoot, absolute).split(path.sep).join("/");
|
|
74
|
+
if (!sourceExtension.test(file) || !project.files.includes(file))
|
|
75
|
+
throw new Error("Compilation database includes a non-inventoried translation unit");
|
|
76
|
+
const declared = entry.arguments[0];
|
|
77
|
+
const compiler = path.basename(declared);
|
|
78
|
+
if ((compiler !== "clang" && compiler !== "clang++") ||
|
|
79
|
+
!(await clangExecutableMatches(compiler, declared)))
|
|
80
|
+
throw new Error("Compilation database must select the registered PATH Clang executable");
|
|
81
|
+
const args = [];
|
|
82
|
+
let inputs = 0;
|
|
83
|
+
let input = "";
|
|
84
|
+
let compileOnly = false;
|
|
85
|
+
for (let i = 1; i < entry.arguments.length; i++) {
|
|
86
|
+
const arg = entry.arguments[i];
|
|
87
|
+
if (arg === "-c") {
|
|
88
|
+
compileOnly = true;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (arg === "-o" || arg === "-MF" || arg === "-MT" || arg === "-MQ") {
|
|
92
|
+
if (!entry.arguments[++i])
|
|
93
|
+
throw new Error("Missing compilation output argument");
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (["-MD", "-MMD", "-MP", "-g", "-g0"].includes(arg))
|
|
97
|
+
continue;
|
|
98
|
+
if (/^-std=(?:c(?:89|90|99|11|17|18|23|2x)|gnu(?:89|90|99|11|17|18|23|2x)|(?:c|gnu)\+\+(?:98|03|11|14|17|20|23|2b|26|2c))$/.test(arg) ||
|
|
99
|
+
/^-O[0-3sgz]$/.test(arg) ||
|
|
100
|
+
["-fPIC", "-fPIE", "-fno-exceptions", "-fno-rtti", "-pthread"].includes(arg) ||
|
|
101
|
+
/^-W(?:all|extra|error|pedantic|conversion|sign-conversion|shadow|unused|unused-parameter|no-unused-parameter)$/.test(arg)) {
|
|
102
|
+
args.push(arg);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const define = /^(-[DU])(.*)$/.exec(arg);
|
|
106
|
+
if (define) {
|
|
107
|
+
const value = define[2] || entry.arguments[++i];
|
|
108
|
+
if (!value ||
|
|
109
|
+
!/^[A-Za-z_][A-Za-z0-9_]*(?:=[^\r\n]*)?$/.test(value) ||
|
|
110
|
+
(define[1] === "-U" && value.includes("=")))
|
|
111
|
+
throw new Error("Unsupported macro argument");
|
|
112
|
+
args.push(define[1], value);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const include = /^(?:-I(.+))$/.exec(arg);
|
|
116
|
+
if (include || ["-I", "-iquote", "-isystem"].includes(arg)) {
|
|
117
|
+
const value = include?.[1] ?? entry.arguments[++i];
|
|
118
|
+
if (!value)
|
|
119
|
+
throw new Error("Missing include directory");
|
|
120
|
+
const directory = await withinRoot(source.root, path.relative(source.root, path.resolve(cwd, value)));
|
|
121
|
+
if (!(await stat(directory)).isDirectory())
|
|
122
|
+
throw new Error("Include path must be a directory");
|
|
123
|
+
args.push(include ? "-I" : arg, value);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (arg.startsWith("-") ||
|
|
127
|
+
arg.startsWith("@") ||
|
|
128
|
+
(await withinRoot(source.root, path.relative(source.root, path.resolve(cwd, arg)))) !== absolute)
|
|
129
|
+
throw new Error("Compilation database uses an unsupported compiler flag or input");
|
|
130
|
+
input = arg;
|
|
131
|
+
inputs++;
|
|
132
|
+
}
|
|
133
|
+
if (!compileOnly || inputs !== 1)
|
|
134
|
+
throw new Error("Compilation database must describe exactly one compile-only source input per entry");
|
|
135
|
+
units.push({
|
|
136
|
+
compiler,
|
|
137
|
+
cwd: path.relative(source.root, cwd).split(path.sep).join("/") || ".",
|
|
138
|
+
file,
|
|
139
|
+
input,
|
|
140
|
+
args,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
if (new Set(units.map((unit) => JSON.stringify(unit))).size !== units.length)
|
|
144
|
+
throw new Error("Duplicate compilation database entry");
|
|
145
|
+
return units;
|
|
146
|
+
}
|
|
147
|
+
export async function clangCheck(source, project) {
|
|
148
|
+
const scope = project.files.filter((file) => inventoriedExtension.test(file));
|
|
149
|
+
const check = {
|
|
150
|
+
id: "cpp.clang-check",
|
|
151
|
+
adapter: project.adapter,
|
|
152
|
+
project: project.path,
|
|
153
|
+
scope,
|
|
154
|
+
kind: "analysis",
|
|
155
|
+
parser: "clang-json",
|
|
156
|
+
commands: [],
|
|
157
|
+
reason: "Check prepared Clang compilation database entries without emitting objects; account for native translation-unit and header dependencies.",
|
|
158
|
+
};
|
|
159
|
+
if (!project.files.includes("compile_commands.json"))
|
|
160
|
+
check.unavailableReason =
|
|
161
|
+
"Prepare an inventoried project-root compile_commands.json with arguments arrays; build systems are not run automatically.";
|
|
162
|
+
else if (!scope.length)
|
|
163
|
+
check.unavailableReason = "No C/C++ source was inventoried";
|
|
164
|
+
else if ([source.root, project.path, ...scope].some((file) => /[\r\n\\$#:]/.test(file)))
|
|
165
|
+
check.unavailableReason =
|
|
166
|
+
"This dependency-file profile does not support newline, backslash, dollar, hash or colon in source paths";
|
|
167
|
+
else if (scope.some((file) => /\.(?:ixx|cppm)$/.test(file)))
|
|
168
|
+
check.unavailableReason =
|
|
169
|
+
"C++ module translation units require a separate verified build profile";
|
|
170
|
+
else {
|
|
171
|
+
try {
|
|
172
|
+
const invocation = JSON.stringify({
|
|
173
|
+
units: await databaseUnits(source, project),
|
|
174
|
+
scope,
|
|
175
|
+
});
|
|
176
|
+
if (Buffer.byteLength(invocation) > 100 * 1024)
|
|
177
|
+
throw new Error("Compilation invocation exceeds the 100 KiB argument limit");
|
|
178
|
+
check.commands.push({
|
|
179
|
+
executable: process.execPath,
|
|
180
|
+
args: [
|
|
181
|
+
fileURLToPath(new URL("./clang-runner.js", import.meta.url)),
|
|
182
|
+
source.root,
|
|
183
|
+
invocation,
|
|
184
|
+
],
|
|
185
|
+
cwd: project.path,
|
|
186
|
+
env: { ...clangEnvironment, PATH: process.env.PATH ?? "" },
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
check.unavailableReason =
|
|
191
|
+
error instanceof Error
|
|
192
|
+
? error.message
|
|
193
|
+
: "Compilation database could not be prepared";
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return check;
|
|
197
|
+
}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createReviewContext, projectReviewContext, receiveReview, projectReviewReceipt, } from "./review.js";
|
|
4
|
+
import { fetchPolicyPack } from "./fetch-pack.js";
|
|
5
|
+
import { externalReferencesSchema, loadExternalAdapters, } from "./external-adapter.js";
|
|
6
|
+
import { runMutations, projectMutations } from "./mutation.js";
|
|
7
|
+
import { retrieveGuidance, projectGuidance } from "./guidance.js";
|
|
8
|
+
import { createFindingBaseline, compareFindings, projectFindingComparison, } from "./finding-policy.js";
|
|
9
|
+
import { checkArchitecture, projectArchitectureReport, } from "./architecture.js";
|
|
10
|
+
import { inheritEnvironment } from "./environment.js";
|
|
11
|
+
import { parseArgs } from "node:util";
|
|
12
|
+
import { realpath } from "node:fs/promises";
|
|
13
|
+
import { adapters } from "./adapters.js";
|
|
14
|
+
import { createPlan, validate } from "./engine.js";
|
|
15
|
+
import { serve } from "./mcp.js";
|
|
16
|
+
import { projectPlan, projectReport } from "./output.js";
|
|
17
|
+
import { exportSarif } from "./sarif.js";
|
|
18
|
+
import { reportSchema } from "./schemas.js";
|
|
19
|
+
import { importJUnit } from "./junit.js";
|
|
20
|
+
import { readProjectFile } from "./inventory.js";
|
|
21
|
+
import { VERSION } from "./types.js";
|
|
22
|
+
import { validateContracts, projectContractReport } from "./contracts.js";
|
|
23
|
+
import { compareRuntimeInventories, projectRuntimeComparison, } from "./runtime-inventory.js";
|
|
24
|
+
async function main() {
|
|
25
|
+
const { values, positionals } = parseArgs({
|
|
26
|
+
allowPositionals: true,
|
|
27
|
+
strict: true,
|
|
28
|
+
options: {
|
|
29
|
+
root: { type: "string", default: "." },
|
|
30
|
+
"trust-project": { type: "boolean", default: false },
|
|
31
|
+
"allow-execution": { type: "boolean", default: false },
|
|
32
|
+
detailed: { type: "boolean", default: false },
|
|
33
|
+
input: { type: "string" },
|
|
34
|
+
context: { type: "string" },
|
|
35
|
+
"allow-review-source": { type: "boolean", default: false },
|
|
36
|
+
url: { type: "string" },
|
|
37
|
+
sha256: { type: "string" },
|
|
38
|
+
output: { type: "string" },
|
|
39
|
+
topic: { type: "string", multiple: true },
|
|
40
|
+
policy: { type: "string" },
|
|
41
|
+
before: { type: "string" },
|
|
42
|
+
after: { type: "string" },
|
|
43
|
+
baseline: { type: "string" },
|
|
44
|
+
"previous-baseline": { type: "string" },
|
|
45
|
+
owner: { type: "string" },
|
|
46
|
+
reason: { type: "string" },
|
|
47
|
+
base: { type: "string" },
|
|
48
|
+
"policy-overlay": { type: "string" },
|
|
49
|
+
adapter: { type: "string", multiple: true },
|
|
50
|
+
"allow-env": { type: "string", multiple: true },
|
|
51
|
+
"timeout-ms": { type: "string", default: "30000" },
|
|
52
|
+
help: { type: "boolean", default: false },
|
|
53
|
+
version: { type: "boolean", default: false },
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
if (values.version) {
|
|
57
|
+
process.stdout.write(`${VERSION}\n`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (values.help || positionals.length === 0) {
|
|
61
|
+
process.stdout.write("checktrail <inspect|plan|run|serve|adapters|import-junit|export-sarif|create-baseline|compare-findings|compare-runtime|check-contracts|check-architecture|guidance|review-context|review-receipt|mutate|fetch-pack> [--root PATH] [--detailed] [--base REVISION] [--policy-overlay PATH] [--adapter PATH#sha256=DIGEST ...]\nRun: --trust-project [--timeout-ms 30000] [--allow-env NAME ...]\nServe: --allow-execution (optional; disabled by default) [--allow-env NAME ...]\nFetch-pack: --url HTTPS_URL --sha256 DIGEST --output RELATIVE_JSON_PATH\nExit: 0 passed/read-only success/completed advisory experiment, 1 failed checks, 2 incomplete/error\n");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (positionals.length !== 1)
|
|
65
|
+
throw new Error("Expected exactly one command");
|
|
66
|
+
const command = positionals[0];
|
|
67
|
+
if (values["allow-review-source"] &&
|
|
68
|
+
(!values.detailed ||
|
|
69
|
+
!["review-context", "review-receipt", "serve"].includes(command)))
|
|
70
|
+
throw new Error("Review source disclosure requires --detailed with review-context, review-receipt or serve");
|
|
71
|
+
if (values.context !== undefined && command !== "review-receipt")
|
|
72
|
+
throw new Error("--context applies only to review-receipt");
|
|
73
|
+
if (command !== "fetch-pack" &&
|
|
74
|
+
(values.url !== undefined ||
|
|
75
|
+
values.sha256 !== undefined ||
|
|
76
|
+
values.output !== undefined))
|
|
77
|
+
throw new Error("Download options apply only to fetch-pack");
|
|
78
|
+
const externalAdapters = externalReferencesSchema.parse((values.adapter ?? []).map((value) => {
|
|
79
|
+
const split = value.lastIndexOf("#sha256=");
|
|
80
|
+
if (split <= 0)
|
|
81
|
+
throw new Error("External adapters require PATH#sha256=DIGEST");
|
|
82
|
+
return {
|
|
83
|
+
path: path.resolve(value.slice(0, split)),
|
|
84
|
+
sha256: value.slice(split + 8),
|
|
85
|
+
};
|
|
86
|
+
}));
|
|
87
|
+
if (externalAdapters.length &&
|
|
88
|
+
!["inspect", "plan", "run", "serve", "adapters", "guidance"].includes(command))
|
|
89
|
+
throw new Error("External adapters apply only to inspection, planning, validation, serving and derived guidance");
|
|
90
|
+
if (externalAdapters.length && command === "guidance" && values.input)
|
|
91
|
+
throw new Error("External adapters require derived guidance, not an imported context");
|
|
92
|
+
const print = (value) => {
|
|
93
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
94
|
+
};
|
|
95
|
+
if (command === "adapters") {
|
|
96
|
+
print([
|
|
97
|
+
...adapters,
|
|
98
|
+
...(await loadExternalAdapters(externalAdapters)).map((item) => ({
|
|
99
|
+
...item.identity,
|
|
100
|
+
markers: item.manifest.markers,
|
|
101
|
+
checks: item.manifest.checks.map((check) => `${item.identity.id}.${check.id}`),
|
|
102
|
+
})),
|
|
103
|
+
]);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const root = await realpath(values.root);
|
|
107
|
+
if (command === "fetch-pack") {
|
|
108
|
+
if (!values.url || !values.sha256 || !values.output)
|
|
109
|
+
throw new Error("fetch-pack requires --url HTTPS_URL --sha256 DIGEST --output RELATIVE_JSON_PATH");
|
|
110
|
+
if (values["trust-project"] ||
|
|
111
|
+
values["allow-execution"] ||
|
|
112
|
+
values.base ||
|
|
113
|
+
values["policy-overlay"] ||
|
|
114
|
+
values["allow-env"]?.length)
|
|
115
|
+
throw new Error("Policy pack download does not accept execution or project policy options");
|
|
116
|
+
const controller = new AbortController();
|
|
117
|
+
const cancel = () => controller.abort();
|
|
118
|
+
process.once("SIGINT", cancel);
|
|
119
|
+
process.once("SIGTERM", cancel);
|
|
120
|
+
try {
|
|
121
|
+
print(await fetchPolicyPack(root, {
|
|
122
|
+
url: values.url,
|
|
123
|
+
sha256: values.sha256,
|
|
124
|
+
output: values.output,
|
|
125
|
+
timeoutMs: Number(values["timeout-ms"]),
|
|
126
|
+
signal: controller.signal,
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
process.removeListener("SIGINT", cancel);
|
|
131
|
+
process.removeListener("SIGTERM", cancel);
|
|
132
|
+
}
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (command === "review-context") {
|
|
136
|
+
if (!values.input)
|
|
137
|
+
throw new Error("review-context requires --input selection.json");
|
|
138
|
+
print(projectReviewContext(await createReviewContext(root, JSON.parse(await readProjectFile(root, values.input))), values["allow-review-source"]));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (command === "review-receipt") {
|
|
142
|
+
if (!values.context || !values.input)
|
|
143
|
+
throw new Error("review-receipt requires --context context.json and --input assessment.json");
|
|
144
|
+
const result = await receiveReview(root, JSON.parse(await readProjectFile(root, values.context)), JSON.parse(await readProjectFile(root, values.input)));
|
|
145
|
+
print(projectReviewReceipt(result, values["allow-review-source"]));
|
|
146
|
+
process.exitCode =
|
|
147
|
+
result.freshness === "current" && result.citations.unmatched === 0
|
|
148
|
+
? 0
|
|
149
|
+
: 2;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (command === "mutate") {
|
|
153
|
+
if (values.base !== undefined ||
|
|
154
|
+
values["policy-overlay"] !== undefined ||
|
|
155
|
+
values["allow-env"]?.length)
|
|
156
|
+
throw new Error("Mutation experiments do not support Git selection, private overlays or environment grants in this profile");
|
|
157
|
+
if (!values["trust-project"])
|
|
158
|
+
throw new Error("Mutation experiments require --trust-project");
|
|
159
|
+
if (!values.input)
|
|
160
|
+
throw new Error("Mutation experiments require --input recipe path");
|
|
161
|
+
const report = await runMutations(root, JSON.parse(await readProjectFile(root, values.input)), {
|
|
162
|
+
trusted: true,
|
|
163
|
+
timeoutMs: Number(values["timeout-ms"]),
|
|
164
|
+
});
|
|
165
|
+
print(projectMutations(report, values.detailed));
|
|
166
|
+
process.exitCode = report.complete ? 0 : 2;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (command === "guidance") {
|
|
170
|
+
if (values.input && values.topic)
|
|
171
|
+
throw new Error("Use either --input context or --topic, not both");
|
|
172
|
+
const context = values.input
|
|
173
|
+
? JSON.parse(await readProjectFile(root, values.input))
|
|
174
|
+
: {
|
|
175
|
+
schemaVersion: 1,
|
|
176
|
+
checks: [
|
|
177
|
+
...new Set((await createPlan(root, {
|
|
178
|
+
externalAdapters,
|
|
179
|
+
environment: inheritEnvironment(values["allow-env"] ?? []),
|
|
180
|
+
...(values.base !== undefined ? { base: values.base } : {}),
|
|
181
|
+
...(values["policy-overlay"] !== undefined
|
|
182
|
+
? { policyOverlay: values["policy-overlay"] }
|
|
183
|
+
: {}),
|
|
184
|
+
})).plan.checks.map((check) => check.id)),
|
|
185
|
+
],
|
|
186
|
+
topics: values.topic ?? [],
|
|
187
|
+
};
|
|
188
|
+
print(projectGuidance(retrieveGuidance(context), values.detailed));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (command === "check-architecture") {
|
|
192
|
+
if (!values.input || !values.policy)
|
|
193
|
+
throw new Error("Architecture validation requires --input graph and --policy boundary artifact paths");
|
|
194
|
+
const result = checkArchitecture(JSON.parse(await readProjectFile(root, values.input)), JSON.parse(await readProjectFile(root, values.policy)));
|
|
195
|
+
print(projectArchitectureReport(result, values.detailed));
|
|
196
|
+
process.exitCode =
|
|
197
|
+
result.outcome === "passed" ? 0 : result.outcome === "failed" ? 1 : 2;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (command === "check-contracts") {
|
|
201
|
+
if (!values.input)
|
|
202
|
+
throw new Error("Contract validation requires --input relative artifact path");
|
|
203
|
+
const result = await validateContracts(JSON.parse(await readProjectFile(root, values.input)), { timeoutMs: Number(values["timeout-ms"]) });
|
|
204
|
+
print(projectContractReport(result, values.detailed));
|
|
205
|
+
process.exitCode =
|
|
206
|
+
result.outcome === "passed" ? 0 : result.outcome === "failed" ? 1 : 2;
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (command === "compare-runtime") {
|
|
210
|
+
if (!values.before || !values.after)
|
|
211
|
+
throw new Error("Runtime comparison requires --before and --after relative artifact paths");
|
|
212
|
+
const result = compareRuntimeInventories(JSON.parse(await readProjectFile(root, values.before)), JSON.parse(await readProjectFile(root, values.after)));
|
|
213
|
+
print(projectRuntimeComparison(result, values.detailed));
|
|
214
|
+
process.exitCode =
|
|
215
|
+
result.outcome === "passed" ? 0 : result.outcome === "failed" ? 1 : 2;
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (command === "create-baseline" || command === "compare-findings") {
|
|
219
|
+
if (!values.input)
|
|
220
|
+
throw new Error("Finding policy requires --input relative/report.json");
|
|
221
|
+
const report = JSON.parse(await readProjectFile(root, values.input));
|
|
222
|
+
if (command === "create-baseline") {
|
|
223
|
+
if (!values.owner || !values.reason)
|
|
224
|
+
throw new Error("Baseline creation requires --owner and --reason");
|
|
225
|
+
const result = createFindingBaseline(report, {
|
|
226
|
+
owner: values.owner,
|
|
227
|
+
reason: values.reason,
|
|
228
|
+
});
|
|
229
|
+
print(values.detailed
|
|
230
|
+
? result
|
|
231
|
+
: {
|
|
232
|
+
schemaVersion: result.schemaVersion,
|
|
233
|
+
provenance: "baseline-draft",
|
|
234
|
+
entries: result.entries.length,
|
|
235
|
+
limits: result.limits,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
if (!values.baseline)
|
|
240
|
+
throw new Error("Comparison requires --baseline relative/baseline.json");
|
|
241
|
+
const previous = values["previous-baseline"] === undefined
|
|
242
|
+
? undefined
|
|
243
|
+
: JSON.parse(await readProjectFile(root, values["previous-baseline"]));
|
|
244
|
+
const result = compareFindings(report, JSON.parse(await readProjectFile(root, values.baseline)), previous === undefined ? {} : { previousBaseline: previous });
|
|
245
|
+
print(projectFindingComparison(result, values.detailed));
|
|
246
|
+
process.exitCode =
|
|
247
|
+
result.outcome === "passed" ? 0 : result.outcome === "failed" ? 1 : 2;
|
|
248
|
+
}
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (command === "export-sarif") {
|
|
252
|
+
if (!values.input)
|
|
253
|
+
throw new Error("SARIF export requires --input relative/report.json");
|
|
254
|
+
const report = reportSchema.parse(JSON.parse(await readProjectFile(root, values.input)));
|
|
255
|
+
print(exportSarif(report));
|
|
256
|
+
process.exitCode =
|
|
257
|
+
report.outcome === "passed" ? 0 : report.outcome === "failed" ? 1 : 2;
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (command === "import-junit") {
|
|
261
|
+
if (!values.input)
|
|
262
|
+
throw new Error("JUnit import requires --input relative/path.xml");
|
|
263
|
+
const result = importJUnit(await readProjectFile(root, values.input));
|
|
264
|
+
print(values.detailed
|
|
265
|
+
? result
|
|
266
|
+
: {
|
|
267
|
+
schemaVersion: result.schemaVersion,
|
|
268
|
+
engineVersion: result.engineVersion,
|
|
269
|
+
format: result.format,
|
|
270
|
+
provenance: result.provenance,
|
|
271
|
+
outcome: result.outcome,
|
|
272
|
+
reason: result.reason,
|
|
273
|
+
...(result.tests ? { tests: result.tests } : {}),
|
|
274
|
+
});
|
|
275
|
+
process.exitCode =
|
|
276
|
+
result.outcome === "passed" ? 0 : result.outcome === "failed" ? 1 : 2;
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
const environment = inheritEnvironment(values["allow-env"] ?? []);
|
|
280
|
+
if (command === "serve") {
|
|
281
|
+
await serve({
|
|
282
|
+
root,
|
|
283
|
+
allowExecution: values["allow-execution"],
|
|
284
|
+
allowReviewSource: values["allow-review-source"],
|
|
285
|
+
detailed: values.detailed,
|
|
286
|
+
environment,
|
|
287
|
+
externalAdapters,
|
|
288
|
+
...(values.base !== undefined ? { base: values.base } : {}),
|
|
289
|
+
...(values["policy-overlay"] !== undefined
|
|
290
|
+
? { policyOverlay: values["policy-overlay"] }
|
|
291
|
+
: {}),
|
|
292
|
+
});
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
if (command === "inspect" || command === "plan") {
|
|
296
|
+
print(projectPlan((await createPlan(root, {
|
|
297
|
+
environment,
|
|
298
|
+
externalAdapters,
|
|
299
|
+
...(values.base !== undefined ? { base: values.base } : {}),
|
|
300
|
+
...(values["policy-overlay"] !== undefined
|
|
301
|
+
? { policyOverlay: values["policy-overlay"] }
|
|
302
|
+
: {}),
|
|
303
|
+
})).plan, values.detailed));
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (command === "run") {
|
|
307
|
+
const controller = new AbortController();
|
|
308
|
+
const cancel = () => controller.abort();
|
|
309
|
+
process.once("SIGINT", cancel);
|
|
310
|
+
process.once("SIGTERM", cancel);
|
|
311
|
+
try {
|
|
312
|
+
const report = await validate(root, {
|
|
313
|
+
trusted: values["trust-project"],
|
|
314
|
+
environment,
|
|
315
|
+
externalAdapters,
|
|
316
|
+
...(values.base !== undefined ? { base: values.base } : {}),
|
|
317
|
+
...(values["policy-overlay"] !== undefined
|
|
318
|
+
? { policyOverlay: values["policy-overlay"] }
|
|
319
|
+
: {}),
|
|
320
|
+
timeoutMs: Number(values["timeout-ms"]),
|
|
321
|
+
signal: controller.signal,
|
|
322
|
+
});
|
|
323
|
+
print(projectReport(report, values.detailed));
|
|
324
|
+
process.exitCode =
|
|
325
|
+
report.outcome === "passed" ? 0 : report.outcome === "failed" ? 1 : 2;
|
|
326
|
+
}
|
|
327
|
+
finally {
|
|
328
|
+
process.removeListener("SIGINT", cancel);
|
|
329
|
+
process.removeListener("SIGTERM", cancel);
|
|
330
|
+
}
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
throw new Error("Unknown command");
|
|
334
|
+
}
|
|
335
|
+
main().catch((error) => {
|
|
336
|
+
process.stderr.write(`${error instanceof Error ? error.message : "Unexpected error"}\n`);
|
|
337
|
+
process.exitCode = 2;
|
|
338
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Inventory } from "./types.js";
|
|
3
|
+
export declare const workspaceSchema: z.ZodObject<{
|
|
4
|
+
complete: z.ZodBoolean;
|
|
5
|
+
dependencies: z.ZodArray<z.ZodObject<{
|
|
6
|
+
consumer: z.ZodString;
|
|
7
|
+
producer: z.ZodString;
|
|
8
|
+
}, z.core.$strict>>;
|
|
9
|
+
}, z.core.$strict>;
|
|
10
|
+
export declare const configSchema: z.ZodObject<{
|
|
11
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
12
|
+
workspace: z.ZodOptional<z.ZodObject<{
|
|
13
|
+
complete: z.ZodBoolean;
|
|
14
|
+
dependencies: z.ZodArray<z.ZodObject<{
|
|
15
|
+
consumer: z.ZodString;
|
|
16
|
+
producer: z.ZodString;
|
|
17
|
+
}, z.core.$strict>>;
|
|
18
|
+
}, z.core.$strict>>;
|
|
19
|
+
projects: z.ZodArray<z.ZodObject<{
|
|
20
|
+
path: z.ZodString;
|
|
21
|
+
checks: z.ZodArray<z.ZodString>;
|
|
22
|
+
packs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
23
|
+
path: z.ZodString;
|
|
24
|
+
sha256: z.ZodString;
|
|
25
|
+
}, z.core.$strict>>>;
|
|
26
|
+
environment: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
27
|
+
}, z.core.$strict>>;
|
|
28
|
+
}, z.core.$strict>;
|
|
29
|
+
export type Config = z.infer<typeof configSchema>;
|
|
30
|
+
export declare function loadConfig(source: Inventory, overlayPath?: string): Promise<{
|
|
31
|
+
config: Config | undefined;
|
|
32
|
+
fingerprint: string;
|
|
33
|
+
}>;
|