@kirrosh/zond 0.22.0 → 0.23.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 +648 -0
- package/README.md +58 -6
- package/package.json +9 -6
- package/src/cli/argv.ts +122 -0
- package/src/cli/commands/add-api.ts +134 -0
- package/src/cli/commands/api/annotate/idempotency.ts +59 -0
- package/src/cli/commands/api/annotate/index.ts +525 -0
- package/src/cli/commands/api/annotate/lifecycle.ts +74 -0
- package/src/cli/commands/api/annotate/overlay.ts +206 -0
- package/src/cli/commands/api/annotate/pagination.ts +60 -0
- package/src/cli/commands/api/annotate/prompts.ts +183 -0
- package/src/cli/commands/api/annotate/readback.ts +58 -0
- package/src/cli/commands/api/annotate/resources.ts +91 -0
- package/src/cli/commands/api/annotate/seed-bodies.ts +61 -0
- package/src/cli/commands/audit.ts +480 -0
- package/src/cli/commands/bootstrap.ts +710 -0
- package/src/cli/commands/catalog.ts +35 -0
- package/src/cli/commands/check.ts +348 -0
- package/src/cli/commands/checks.ts +756 -0
- package/src/cli/commands/ci-init.ts +43 -0
- package/src/cli/commands/clean.ts +212 -0
- package/src/cli/commands/cleanup.ts +262 -0
- package/src/cli/commands/completions.ts +16 -0
- package/src/cli/commands/coverage.ts +605 -132
- package/src/cli/commands/db.ts +178 -7
- package/src/cli/commands/describe.ts +37 -2
- package/src/cli/commands/discover.ts +1236 -0
- package/src/cli/commands/doctor.ts +607 -0
- package/src/cli/commands/fixtures.ts +402 -0
- package/src/cli/commands/generate.ts +420 -46
- package/src/cli/commands/init/bootstrap.ts +30 -1
- package/src/cli/commands/{init.ts → init/index.ts} +99 -5
- package/src/cli/commands/init/skills.ts +56 -3
- package/src/cli/commands/init/templates/agents.md +65 -61
- package/src/cli/commands/init/templates/skills/zond-checks.md +397 -0
- package/src/cli/commands/init/templates/skills/zond-triage.md +210 -0
- package/src/cli/commands/init/templates/skills/zond.md +592 -125
- package/src/cli/commands/init/templates/zond-config.yml +8 -9
- package/src/cli/commands/prepare-fixtures.ts +135 -0
- package/src/cli/commands/probe/mass-assignment.ts +503 -0
- package/src/cli/commands/probe/security.ts +454 -0
- package/src/cli/commands/probe/static.ts +255 -0
- package/src/cli/commands/probe/webhooks.ts +161 -0
- package/src/cli/commands/probe.ts +459 -0
- package/src/cli/commands/reference.ts +87 -0
- package/src/cli/commands/refresh-api.ts +169 -0
- package/src/cli/commands/remove-api.ts +150 -0
- package/src/cli/commands/report-bundle.ts +318 -0
- package/src/cli/commands/report.ts +241 -0
- package/src/cli/commands/request.ts +379 -4
- package/src/cli/commands/run.ts +842 -53
- package/src/cli/commands/session.ts +244 -0
- package/src/cli/commands/use.ts +18 -1
- package/src/cli/index.ts +20 -3
- package/src/cli/json-envelope.ts +112 -3
- package/src/cli/json-schemas.ts +263 -0
- package/src/cli/program.ts +198 -635
- package/src/cli/resolve.ts +105 -0
- package/src/cli/status-filter.ts +124 -0
- package/src/cli/util/api-context.ts +85 -0
- package/src/cli/version.ts +5 -0
- package/src/core/anti-fp/bootstrap.ts +34 -0
- package/src/core/anti-fp/index.ts +33 -0
- package/src/core/anti-fp/registry.ts +44 -0
- package/src/core/anti-fp/rules/baseline-echo.ts +74 -0
- package/src/core/anti-fp/rules/schemathesis/body_negation_becomes_valid.ts +52 -0
- package/src/core/anti-fp/rules/schemathesis/coverage_phase_boundary_positive.ts +38 -0
- package/src/core/anti-fp/rules/schemathesis/has_unverifiable_mutations.ts +35 -0
- package/src/core/anti-fp/rules/schemathesis/index.ts +24 -0
- package/src/core/anti-fp/rules/schemathesis/string_type_mutation_becomes_valid.ts +53 -0
- package/src/core/anti-fp/rules/subscription-gated/index.ts +11 -0
- package/src/core/anti-fp/rules/subscription-gated/paid-plan-403.ts +75 -0
- package/src/core/anti-fp/types.ts +68 -0
- package/src/core/checks/checks/_crud-helpers.ts +133 -0
- package/src/core/checks/checks/_negative_mutator.ts +133 -0
- package/src/core/checks/checks/_readback-helpers.ts +133 -0
- package/src/core/checks/checks/content_type_conformance.ts +39 -0
- package/src/core/checks/checks/cross_call_references.ts +134 -0
- package/src/core/checks/checks/ensure_resource_availability.ts +62 -0
- package/src/core/checks/checks/idempotency_replay.ts +246 -0
- package/src/core/checks/checks/ignored_auth.ts +211 -0
- package/src/core/checks/checks/index.ts +65 -0
- package/src/core/checks/checks/lifecycle_transitions.ts +273 -0
- package/src/core/checks/checks/missing_required_header.ts +40 -0
- package/src/core/checks/checks/negative_data_rejection.ts +45 -0
- package/src/core/checks/checks/not_a_server_error.ts +27 -0
- package/src/core/checks/checks/open_cors_on_sensitive.ts +131 -0
- package/src/core/checks/checks/pagination_invariants.ts +238 -0
- package/src/core/checks/checks/positive_data_acceptance.ts +36 -0
- package/src/core/checks/checks/rate_limit_headers_absent.ts +77 -0
- package/src/core/checks/checks/response_headers_conformance.ts +74 -0
- package/src/core/checks/checks/response_schema_conformance.ts +30 -0
- package/src/core/checks/checks/status_code_conformance.ts +61 -0
- package/src/core/checks/checks/unsupported_method.ts +63 -0
- package/src/core/checks/checks/use_after_free.ts +78 -0
- package/src/core/checks/index.ts +30 -0
- package/src/core/checks/mode.ts +79 -0
- package/src/core/checks/recommended-action.ts +64 -0
- package/src/core/checks/registry.ts +78 -0
- package/src/core/checks/runner.ts +874 -0
- package/src/core/checks/sarif.ts +230 -0
- package/src/core/checks/stateful.ts +121 -0
- package/src/core/checks/types.ts +189 -0
- package/src/core/classifier/recommended-action.ts +222 -0
- package/src/core/context/current.ts +22 -6
- package/src/core/context/session.ts +78 -0
- package/src/core/coverage/loader.ts +185 -0
- package/src/core/coverage/reasons.ts +300 -0
- package/src/core/diagnostics/db-analysis.ts +151 -11
- package/src/core/diagnostics/failure-class.ts +120 -0
- package/src/core/diagnostics/failure-hints.ts +212 -9
- package/src/core/diagnostics/spec-pointer.ts +99 -0
- package/src/core/diagnostics/suggested-fixes.ts +156 -0
- package/src/core/exporter/case-study/index.ts +270 -0
- package/src/core/exporter/curl.ts +40 -0
- package/src/core/exporter/exporter.ts +48 -0
- package/src/core/exporter/html-report/escape.ts +24 -0
- package/src/core/exporter/html-report/index.ts +479 -0
- package/src/core/exporter/html-report/script.ts +100 -0
- package/src/core/exporter/html-report/styles.ts +408 -0
- package/src/core/generator/chunker.ts +42 -16
- package/src/core/generator/coverage-phase.ts +0 -0
- package/src/core/generator/create-body.ts +89 -0
- package/src/core/generator/data-factory.ts +445 -19
- package/src/core/generator/describe.ts +1 -1
- package/src/core/generator/fixtures-builder.ts +325 -0
- package/src/core/generator/index.ts +7 -5
- package/src/core/generator/openapi-reader.ts +37 -3
- package/src/core/generator/path-param-disambig.ts +114 -0
- package/src/core/generator/resources-builder.ts +648 -0
- package/src/core/generator/schema-utils.ts +11 -3
- package/src/core/generator/serializer.ts +103 -13
- package/src/core/generator/suite-generator.ts +419 -111
- package/src/core/generator/types.ts +8 -0
- package/src/core/identity/identity-file.ts +129 -0
- package/src/core/lint/affects.ts +28 -0
- package/src/core/lint/config.ts +96 -0
- package/src/core/lint/format.ts +42 -0
- package/src/core/lint/index.ts +94 -0
- package/src/core/lint/reporter.ts +128 -0
- package/src/core/lint/rules/consistency.ts +158 -0
- package/src/core/lint/rules/heuristics.ts +97 -0
- package/src/core/lint/rules/strictness.ts +109 -0
- package/src/core/lint/types.ts +96 -0
- package/src/core/lint/walker.ts +248 -0
- package/src/core/meta/meta-store.ts +6 -73
- package/src/core/output/README.md +91 -0
- package/src/core/output/index.ts +13 -0
- package/src/core/output/run.ts +126 -0
- package/src/core/output/types.ts +129 -0
- package/src/core/parser/env-interpolation.ts +104 -0
- package/src/core/parser/filter.ts +57 -0
- package/src/core/parser/schema.ts +129 -4
- package/src/core/parser/types.ts +19 -1
- package/src/core/parser/variables.ts +0 -0
- package/src/core/parser/yaml-parser.ts +58 -12
- package/src/core/probe/bootstrap.ts +34 -0
- package/src/core/probe/dry-run-envelope.ts +57 -0
- package/src/core/probe/mass-assignment-probe-class.ts +198 -0
- package/src/core/probe/mass-assignment-probe.ts +1122 -0
- package/src/core/probe/mass-assignment-template.ts +212 -0
- package/src/core/probe/method-probe.ts +43 -76
- package/src/core/probe/method-shared.ts +69 -0
- package/src/core/probe/negative-probe.ts +183 -149
- package/src/core/probe/orphan-tracker.ts +188 -0
- package/src/core/probe/path-discovery.ts +440 -0
- package/src/core/probe/probe-harness.ts +120 -0
- package/src/core/probe/registry.ts +89 -0
- package/src/core/probe/runner.ts +136 -0
- package/src/core/probe/security-probe-class.ts +201 -0
- package/src/core/probe/security-probe.ts +1453 -0
- package/src/core/probe/shared.ts +505 -0
- package/src/core/probe/static-probe-class.ts +125 -0
- package/src/core/probe/types.ts +165 -0
- package/src/core/probe/verdict-aggregator.ts +33 -0
- package/src/core/probe/webhooks-probe.ts +284 -0
- package/src/core/reporter/console.ts +41 -2
- package/src/core/reporter/index.ts +2 -3
- package/src/core/reporter/json.ts +11 -1
- package/src/core/reporter/junit.ts +27 -12
- package/src/core/reporter/ndjson.ts +37 -0
- package/src/core/reporter/types.ts +3 -0
- package/src/core/runner/assertions.ts +58 -1
- package/src/core/runner/async-pool.ts +108 -0
- package/src/core/runner/auth-path.ts +8 -0
- package/src/core/runner/ci-context.ts +72 -0
- package/src/core/runner/executor.ts +264 -20
- package/src/core/runner/form-encode.ts +51 -0
- package/src/core/runner/http-client.ts +75 -2
- package/src/core/runner/learn-drift.ts +293 -0
- package/src/core/runner/preflight-vars.ts +149 -0
- package/src/core/runner/progress-tracker.ts +73 -0
- package/src/core/runner/rate-limiter.ts +89 -17
- package/src/core/runner/run-kind.ts +39 -0
- package/src/core/runner/schema-validator.ts +312 -0
- package/src/core/runner/send-request.ts +153 -20
- package/src/core/runner/types.ts +38 -0
- package/src/core/secrets/registry.ts +164 -0
- package/src/core/secrets/secrets-file.ts +115 -0
- package/src/core/selectors/operation-filter.ts +144 -0
- package/src/core/setup-api.ts +415 -16
- package/src/core/severity/category.ts +94 -0
- package/src/core/severity/index.ts +121 -0
- package/src/core/spec/layers.ts +154 -0
- package/src/core/util/format-eta.ts +21 -0
- package/src/core/utils.ts +5 -1
- package/src/core/workspace/config.ts +129 -0
- package/src/core/workspace/manifest.ts +283 -0
- package/src/core/workspace/output-rotation.ts +62 -0
- package/src/core/workspace/triage-path.ts +87 -0
- package/src/db/lint-runs.ts +47 -0
- package/src/db/migrate.ts +126 -0
- package/src/db/migrations/0001_run_kind.sql +25 -0
- package/src/db/migrations/sql.d.ts +4 -0
- package/src/db/queries/collections.ts +133 -0
- package/src/db/queries/coverage.ts +9 -0
- package/src/db/queries/dashboard.ts +59 -0
- package/src/db/queries/results.ts +128 -0
- package/src/db/queries/runs.ts +235 -0
- package/src/db/queries/sessions.ts +42 -0
- package/src/db/queries/settings.ts +28 -0
- package/src/db/queries/types.ts +172 -0
- package/src/db/queries.ts +72 -802
- package/src/db/schema.ts +178 -50
- package/src/cli/commands/export.ts +0 -144
- package/src/cli/commands/guide.ts +0 -127
- package/src/cli/commands/init/templates/skills/scenarios.md +0 -97
- package/src/cli/commands/probe-methods.ts +0 -108
- package/src/cli/commands/probe-validation.ts +0 -124
- package/src/cli/commands/serve.ts +0 -114
- package/src/cli/commands/sync.ts +0 -268
- package/src/cli/commands/update.ts +0 -189
- package/src/cli/commands/validate.ts +0 -34
- package/src/core/diagnostics/render-md.ts +0 -112
- package/src/core/exporter/postman.ts +0 -963
- package/src/core/generator/guide-builder.ts +0 -253
- package/src/core/meta/types.ts +0 -19
- package/src/core/parser/index.ts +0 -21
- package/src/core/runner/execute-run.ts +0 -132
- package/src/core/runner/index.ts +0 -12
- package/src/core/sync/spec-differ.ts +0 -38
- package/src/web/data/collection-state.ts +0 -362
- package/src/web/routes/api.ts +0 -314
- package/src/web/routes/dashboard.ts +0 -350
- package/src/web/routes/runs.ts +0 -64
- package/src/web/schemas.ts +0 -121
- package/src/web/server.ts +0 -134
- package/src/web/static/htmx.min.cjs +0 -1
- package/src/web/static/style.css +0 -1148
- package/src/web/views/endpoints-tab.ts +0 -174
- package/src/web/views/explorer-tab.ts +0 -402
- package/src/web/views/health-strip.ts +0 -92
- package/src/web/views/layout.ts +0 -48
- package/src/web/views/results.ts +0 -210
- package/src/web/views/runs-tab.ts +0 -126
- package/src/web/views/suites-tab.ts +0 -181
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public entry point for the `core/checks` framework.
|
|
3
|
+
*
|
|
4
|
+
* Importing this module also triggers `checks/index.ts` which registers
|
|
5
|
+
* the built-in checks exactly once.
|
|
6
|
+
*/
|
|
7
|
+
export type {
|
|
8
|
+
Check,
|
|
9
|
+
CheckCase,
|
|
10
|
+
CheckContext,
|
|
11
|
+
CheckFinding,
|
|
12
|
+
CheckOutcome,
|
|
13
|
+
CheckResponse,
|
|
14
|
+
CheckRunData,
|
|
15
|
+
CheckRunSummary,
|
|
16
|
+
Phase,
|
|
17
|
+
Severity,
|
|
18
|
+
} from "./types.ts";
|
|
19
|
+
export { emptySummary } from "./types.ts";
|
|
20
|
+
export {
|
|
21
|
+
__resetRegistryForTests,
|
|
22
|
+
getCheck,
|
|
23
|
+
listChecks,
|
|
24
|
+
registerCheck,
|
|
25
|
+
selectChecks,
|
|
26
|
+
type SelectOptions,
|
|
27
|
+
type SelectionResult,
|
|
28
|
+
} from "./registry.ts";
|
|
29
|
+
export { runChecks, type RunChecksOptions, type RunChecksResult } from "./runner.ts";
|
|
30
|
+
export { registerBuiltinChecks } from "./checks/index.ts";
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `--mode positive|negative|all` filter (m-15 ARV-7).
|
|
3
|
+
*
|
|
4
|
+
* Splits the registered check catalog along the positive-vs-negative
|
|
5
|
+
* axis so an agent can run *just* contract verification (positive) or
|
|
6
|
+
* *just* malicious-input probes (negative) on the same spec without
|
|
7
|
+
* juggling a long `--check` list.
|
|
8
|
+
*
|
|
9
|
+
* Centralized table — both response-phase `Check`s and stateful
|
|
10
|
+
* security checks declare their mode here. Tests snapshot the table so
|
|
11
|
+
* adding a new check forces an explicit decision rather than letting it
|
|
12
|
+
* silently land in the "all" bucket and surface in both modes.
|
|
13
|
+
*/
|
|
14
|
+
import type { Check } from "./types.ts";
|
|
15
|
+
import type { StatefulCheck } from "./stateful.ts";
|
|
16
|
+
|
|
17
|
+
export type Mode = "positive" | "negative" | "all";
|
|
18
|
+
|
|
19
|
+
export const MODE_BY_CHECK: Record<string, Mode> = {
|
|
20
|
+
// Conformance checks fire on every response — both modes.
|
|
21
|
+
not_a_server_error: "all",
|
|
22
|
+
status_code_conformance: "all",
|
|
23
|
+
content_type_conformance: "all",
|
|
24
|
+
response_headers_conformance: "all",
|
|
25
|
+
response_schema_conformance: "all",
|
|
26
|
+
// Probes that *only* make sense as malicious input.
|
|
27
|
+
missing_required_header: "negative",
|
|
28
|
+
unsupported_method: "negative",
|
|
29
|
+
negative_data_rejection: "negative",
|
|
30
|
+
// The "happy-path didn't break" sanity probe.
|
|
31
|
+
positive_data_acceptance: "positive",
|
|
32
|
+
// Security checks (stateful) — they verify a *bad* outcome (auth
|
|
33
|
+
// bypass, dangling reads). Not part of the positive contract.
|
|
34
|
+
ignored_auth: "negative",
|
|
35
|
+
use_after_free: "negative",
|
|
36
|
+
// Availability is positive-flavored — it asserts the server *can*
|
|
37
|
+
// serve the listed resource. Useful in `--mode positive` runs.
|
|
38
|
+
ensure_resource_availability: "all",
|
|
39
|
+
// ARV-169 (m-20): cross-call drift is a contract-verification check
|
|
40
|
+
// (does GET reflect POST?), not a malicious-input probe. Positive.
|
|
41
|
+
cross_call_references: "positive",
|
|
42
|
+
// ARV-170 (m-20): idempotency replay verifies a *contract* the server
|
|
43
|
+
// advertises (Idempotency-Key honored). Positive.
|
|
44
|
+
idempotency_replay: "positive",
|
|
45
|
+
// ARV-171 (m-20): pagination invariants verify the cursor contract.
|
|
46
|
+
pagination_invariants: "positive",
|
|
47
|
+
// ARV-172 (m-20): lifecycle verifies the declared state machine.
|
|
48
|
+
lifecycle_transitions: "positive",
|
|
49
|
+
// ARV-256 (m-21): open-CORS check sends an attacker Origin and
|
|
50
|
+
// inspects response — categorically negative-mode probe.
|
|
51
|
+
open_cors_on_sensitive: "negative",
|
|
52
|
+
// ARV-256 (m-21): rate-limit headers check inspects 2xx responses
|
|
53
|
+
// for advertised rate-limit metadata — runs on the positive path.
|
|
54
|
+
rate_limit_headers_absent: "positive",
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export function modeFor(checkId: string): Mode {
|
|
58
|
+
return MODE_BY_CHECK[checkId] ?? "all";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function filterChecksByMode<T extends Check | StatefulCheck>(
|
|
62
|
+
checks: T[],
|
|
63
|
+
mode: Mode,
|
|
64
|
+
): T[] {
|
|
65
|
+
if (mode === "all") return checks;
|
|
66
|
+
return checks.filter((c) => {
|
|
67
|
+
const cm = modeFor(c.id);
|
|
68
|
+
if (cm === "all") return true;
|
|
69
|
+
return cm === mode;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** True if a built case (with `mode: "positive" | "negative"`) should be
|
|
74
|
+
* sent in the requested run-mode. The runner uses this to short-circuit
|
|
75
|
+
* request emission for cases the active mode doesn't care about. */
|
|
76
|
+
export function caseMatchesMode(caseMode: "positive" | "negative", runMode: Mode): boolean {
|
|
77
|
+
if (runMode === "all") return true;
|
|
78
|
+
return runMode === caseMode;
|
|
79
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ARV-11 (m-15): per-check `recommended_action` table.
|
|
3
|
+
*
|
|
4
|
+
* Each `CheckFinding` carries one closed-enum action so an agent can
|
|
5
|
+
* route on it without parsing the free-form `message`. The mapping is
|
|
6
|
+
* deterministic — given the check id and (for a couple of fan-out cases)
|
|
7
|
+
* the response status, exactly one action comes out.
|
|
8
|
+
*
|
|
9
|
+
* Keep this file thin and table-driven. The shared enum lives in
|
|
10
|
+
* `core/diagnostics/failure-hints.ts` so `db diagnose` (TASK-294) and
|
|
11
|
+
* `zond checks run` (ARV-11) can never drift.
|
|
12
|
+
*/
|
|
13
|
+
import type { RecommendedAction } from "../diagnostics/failure-hints.ts";
|
|
14
|
+
import { classify, type FindingClass } from "../classifier/recommended-action.ts";
|
|
15
|
+
|
|
16
|
+
/** Check IDs the classifier explicitly recognises. Keeping this typed
|
|
17
|
+
* guarantees that adding a new check forces a branch in the classifier
|
|
18
|
+
* switch (tsc errors out at compile time on a stale `STATIC_TABLE` lookup). */
|
|
19
|
+
const CHECK_ID_TO_CLASS: Record<string, FindingClass> = {
|
|
20
|
+
status_code_conformance: "check:status_code_conformance",
|
|
21
|
+
content_type_conformance: "check:content_type_conformance",
|
|
22
|
+
response_headers_conformance: "check:response_headers_conformance",
|
|
23
|
+
response_schema_conformance: "check:response_schema_conformance",
|
|
24
|
+
not_a_server_error: "check:not_a_server_error",
|
|
25
|
+
unsupported_method: "check:unsupported_method",
|
|
26
|
+
positive_data_acceptance: "check:positive_data_acceptance",
|
|
27
|
+
use_after_free: "check:use_after_free",
|
|
28
|
+
ensure_resource_availability: "check:ensure_resource_availability",
|
|
29
|
+
negative_data_rejection: "check:negative_data_rejection",
|
|
30
|
+
missing_required_header: "check:missing_required_header",
|
|
31
|
+
ignored_auth: "check:ignored_auth",
|
|
32
|
+
cross_call_references: "check:cross_call_references",
|
|
33
|
+
idempotency_replay: "check:idempotency_replay",
|
|
34
|
+
pagination_invariants: "check:pagination_invariants",
|
|
35
|
+
lifecycle_transitions: "check:lifecycle_transitions",
|
|
36
|
+
open_cors_on_sensitive: "check:open_cors_on_sensitive",
|
|
37
|
+
rate_limit_headers_absent: "check:rate_limit_headers_absent",
|
|
38
|
+
network_error: "check:network_error",
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* ARV-56: thin wrapper that maps a check id + status to the unified
|
|
43
|
+
* classifier. Returns `undefined` when the check id isn't in the table
|
|
44
|
+
* — unknown ids are a bug in this map, not a runtime input to coerce.
|
|
45
|
+
*/
|
|
46
|
+
export function recommendForCheck(
|
|
47
|
+
checkId: string,
|
|
48
|
+
status?: number,
|
|
49
|
+
): RecommendedAction | undefined {
|
|
50
|
+
const findingClass = CHECK_ID_TO_CLASS[checkId];
|
|
51
|
+
if (!findingClass) return undefined;
|
|
52
|
+
return classify({ finding_class: findingClass, status: status ?? null });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Test-only export — keeps the unit table authoritative without
|
|
56
|
+
* re-listing entries inside the test file. Derived from classifier
|
|
57
|
+
* output so the table never drifts from the classifier's switch. */
|
|
58
|
+
export const RECOMMENDED_ACTION_TABLE: Readonly<Record<string, RecommendedAction>> = Object.freeze(
|
|
59
|
+
Object.fromEntries(
|
|
60
|
+
Object.entries(CHECK_ID_TO_CLASS)
|
|
61
|
+
.filter(([id]) => id !== "network_error") // dynamic — depends on status
|
|
62
|
+
.map(([id, fc]) => [id, classify({ finding_class: fc })!]),
|
|
63
|
+
),
|
|
64
|
+
);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global registry of `zond checks`. Built-in checks register themselves
|
|
3
|
+
* on first import (see `checks/index.ts`); `selectChecks` resolves the
|
|
4
|
+
* `--check` / `--exclude-check` filters from the CLI into the active
|
|
5
|
+
* subset for a single run.
|
|
6
|
+
*/
|
|
7
|
+
import type { Check } from "./types.ts";
|
|
8
|
+
|
|
9
|
+
const REGISTRY = new Map<string, Check>();
|
|
10
|
+
|
|
11
|
+
export function registerCheck(check: Check): void {
|
|
12
|
+
if (REGISTRY.has(check.id)) {
|
|
13
|
+
throw new Error(`Check "${check.id}" is already registered`);
|
|
14
|
+
}
|
|
15
|
+
REGISTRY.set(check.id, check);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getCheck(id: string): Check | undefined {
|
|
19
|
+
return REGISTRY.get(id);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function listChecks(): Check[] {
|
|
23
|
+
return [...REGISTRY.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SelectOptions {
|
|
27
|
+
include?: string[];
|
|
28
|
+
exclude?: string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SelectionResult {
|
|
32
|
+
selected: Check[];
|
|
33
|
+
unknown: string[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Resolve include/exclude id lists into the active set of checks.
|
|
38
|
+
* Unknown ids are returned separately so the caller can surface them as
|
|
39
|
+
* envelope warnings (and decide whether to fail or continue).
|
|
40
|
+
*/
|
|
41
|
+
export function selectChecks(opts: SelectOptions = {}): SelectionResult {
|
|
42
|
+
const all = listChecks();
|
|
43
|
+
const knownIds = new Set(all.map(c => c.id));
|
|
44
|
+
const unknown: string[] = [];
|
|
45
|
+
|
|
46
|
+
for (const id of [...(opts.include ?? []), ...(opts.exclude ?? [])]) {
|
|
47
|
+
if (!knownIds.has(id)) unknown.push(id);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let pool = all;
|
|
51
|
+
if (opts.include && opts.include.length > 0) {
|
|
52
|
+
const includeSet = new Set(opts.include);
|
|
53
|
+
pool = pool.filter(c => includeSet.has(c.id));
|
|
54
|
+
}
|
|
55
|
+
if (opts.exclude && opts.exclude.length > 0) {
|
|
56
|
+
const excludeSet = new Set(opts.exclude);
|
|
57
|
+
pool = pool.filter(c => !excludeSet.has(c.id));
|
|
58
|
+
}
|
|
59
|
+
return { selected: pool, unknown };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Test-only escape hatch — wipes the registry between unit tests. */
|
|
63
|
+
export function __resetRegistryForTests(): void {
|
|
64
|
+
REGISTRY.clear();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Test-only snapshot/restore. Use when a test wants a clean slate but the
|
|
68
|
+
* rest of the suite still needs the side-effect-registered built-ins
|
|
69
|
+
* (otherwise wiping the registry leaks across files because the modules
|
|
70
|
+
* that registered them are already cached and won't re-fire on re-import).
|
|
71
|
+
*/
|
|
72
|
+
export function __snapshotRegistryForTests(): () => void {
|
|
73
|
+
const saved = new Map(REGISTRY);
|
|
74
|
+
return () => {
|
|
75
|
+
REGISTRY.clear();
|
|
76
|
+
for (const [k, v] of saved) REGISTRY.set(k, v);
|
|
77
|
+
};
|
|
78
|
+
}
|