@kirrosh/zond 0.26.0 → 0.27.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.
Files changed (261) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +22 -21
  3. package/bin/zond.mjs +23 -0
  4. package/package.json +13 -16
  5. package/scripts/npm/postinstall.mjs +76 -0
  6. package/src/CLAUDE.md +0 -112
  7. package/src/bun-types.d.ts +0 -5
  8. package/src/cli/argv.ts +0 -122
  9. package/src/cli/commands/add-api.ts +0 -146
  10. package/src/cli/commands/api/annotate/idempotency.ts +0 -59
  11. package/src/cli/commands/api/annotate/index.ts +0 -880
  12. package/src/cli/commands/api/annotate/lifecycle.ts +0 -74
  13. package/src/cli/commands/api/annotate/overlay.ts +0 -206
  14. package/src/cli/commands/api/annotate/pagination.ts +0 -64
  15. package/src/cli/commands/api/annotate/prompts.ts +0 -220
  16. package/src/cli/commands/api/annotate/readback.ts +0 -58
  17. package/src/cli/commands/api/annotate/resources.ts +0 -91
  18. package/src/cli/commands/api/annotate/seed-bodies.ts +0 -61
  19. package/src/cli/commands/audit.ts +0 -786
  20. package/src/cli/commands/catalog.ts +0 -97
  21. package/src/cli/commands/check.ts +0 -361
  22. package/src/cli/commands/checks.ts +0 -1072
  23. package/src/cli/commands/ci-init.ts +0 -223
  24. package/src/cli/commands/clean.ts +0 -212
  25. package/src/cli/commands/cleanup.ts +0 -236
  26. package/src/cli/commands/completions.ts +0 -192
  27. package/src/cli/commands/coverage.ts +0 -872
  28. package/src/cli/commands/db.ts +0 -611
  29. package/src/cli/commands/describe.ts +0 -120
  30. package/src/cli/commands/discover.ts +0 -1356
  31. package/src/cli/commands/doctor.ts +0 -661
  32. package/src/cli/commands/fixtures.ts +0 -402
  33. package/src/cli/commands/generate.ts +0 -577
  34. package/src/cli/commands/init/agents-md.ts +0 -61
  35. package/src/cli/commands/init/bootstrap.ts +0 -111
  36. package/src/cli/commands/init/index.ts +0 -244
  37. package/src/cli/commands/init/skills.ts +0 -141
  38. package/src/cli/commands/init/templates/agents.md +0 -86
  39. package/src/cli/commands/init/templates/markdown.d.ts +0 -4
  40. package/src/cli/commands/init/templates/skills/warm-up-target.md +0 -122
  41. package/src/cli/commands/init/templates/skills/zond-checks.md +0 -621
  42. package/src/cli/commands/init/templates/skills/zond-seed.md +0 -114
  43. package/src/cli/commands/init/templates/skills/zond-triage.md +0 -272
  44. package/src/cli/commands/init/templates/skills/zond.md +0 -861
  45. package/src/cli/commands/init/templates/zond-config.yml +0 -14
  46. package/src/cli/commands/prepare-fixtures.ts +0 -97
  47. package/src/cli/commands/probe/_seed-bodies.ts +0 -52
  48. package/src/cli/commands/probe/mass-assignment.ts +0 -594
  49. package/src/cli/commands/probe/security.ts +0 -537
  50. package/src/cli/commands/probe/static.ts +0 -255
  51. package/src/cli/commands/probe/webhooks.ts +0 -163
  52. package/src/cli/commands/probe.ts +0 -535
  53. package/src/cli/commands/reference.ts +0 -87
  54. package/src/cli/commands/refresh-api.ts +0 -227
  55. package/src/cli/commands/remove-api.ts +0 -150
  56. package/src/cli/commands/report-bundle.ts +0 -310
  57. package/src/cli/commands/report.ts +0 -241
  58. package/src/cli/commands/request.ts +0 -548
  59. package/src/cli/commands/run.ts +0 -1142
  60. package/src/cli/commands/schema-from-runs.ts +0 -128
  61. package/src/cli/commands/secrets.ts +0 -133
  62. package/src/cli/commands/session.ts +0 -244
  63. package/src/cli/commands/use.ts +0 -74
  64. package/src/cli/index.ts +0 -55
  65. package/src/cli/json-envelope.ts +0 -108
  66. package/src/cli/json-schemas.ts +0 -314
  67. package/src/cli/output.ts +0 -40
  68. package/src/cli/program.ts +0 -219
  69. package/src/cli/resolve.ts +0 -105
  70. package/src/cli/runtime.ts +0 -7
  71. package/src/cli/safe-live.ts +0 -24
  72. package/src/cli/status-filter.ts +0 -114
  73. package/src/cli/util/api-context.ts +0 -85
  74. package/src/cli/version.ts +0 -8
  75. package/src/core/audit/persist.ts +0 -183
  76. package/src/core/checks/budget.ts +0 -59
  77. package/src/core/checks/checks/_crud-helpers.ts +0 -133
  78. package/src/core/checks/checks/_negative_mutator.ts +0 -133
  79. package/src/core/checks/checks/_readback-helpers.ts +0 -133
  80. package/src/core/checks/checks/content_type_conformance.ts +0 -39
  81. package/src/core/checks/checks/cross_call_references.ts +0 -147
  82. package/src/core/checks/checks/cursor_boundary_fuzzing.ts +0 -219
  83. package/src/core/checks/checks/ensure_resource_availability.ts +0 -62
  84. package/src/core/checks/checks/idempotency_replay.ts +0 -242
  85. package/src/core/checks/checks/ignored_auth.ts +0 -254
  86. package/src/core/checks/checks/index.ts +0 -68
  87. package/src/core/checks/checks/lifecycle_transitions.ts +0 -416
  88. package/src/core/checks/checks/missing_required_header.ts +0 -40
  89. package/src/core/checks/checks/negative_data_rejection.ts +0 -148
  90. package/src/core/checks/checks/not_a_server_error.ts +0 -35
  91. package/src/core/checks/checks/open_cors_on_sensitive.ts +0 -160
  92. package/src/core/checks/checks/pagination_invariants.ts +0 -419
  93. package/src/core/checks/checks/positive_data_acceptance.ts +0 -33
  94. package/src/core/checks/checks/rate_limit_headers_absent.ts +0 -77
  95. package/src/core/checks/checks/response_headers_conformance.ts +0 -74
  96. package/src/core/checks/checks/response_schema_conformance.ts +0 -30
  97. package/src/core/checks/checks/status_code_conformance.ts +0 -132
  98. package/src/core/checks/checks/unsupported_method.ts +0 -63
  99. package/src/core/checks/checks/use_after_free.ts +0 -78
  100. package/src/core/checks/index.ts +0 -30
  101. package/src/core/checks/mode.ts +0 -82
  102. package/src/core/checks/recommended-action.ts +0 -68
  103. package/src/core/checks/registry.ts +0 -78
  104. package/src/core/checks/runner.ts +0 -1461
  105. package/src/core/checks/sarif.ts +0 -230
  106. package/src/core/checks/spec-findings.ts +0 -308
  107. package/src/core/checks/stateful.ts +0 -121
  108. package/src/core/checks/types.ts +0 -305
  109. package/src/core/checks/zond-extensions.ts +0 -73
  110. package/src/core/classifier/recommended-action.ts +0 -251
  111. package/src/core/context/current.ts +0 -51
  112. package/src/core/context/session.ts +0 -78
  113. package/src/core/coverage/loader.ts +0 -216
  114. package/src/core/coverage/reasons.ts +0 -300
  115. package/src/core/diagnostics/db-analysis.ts +0 -666
  116. package/src/core/diagnostics/failure-class.ts +0 -140
  117. package/src/core/diagnostics/failure-hints.ts +0 -112
  118. package/src/core/diagnostics/spec-pointer.ts +0 -99
  119. package/src/core/diagnostics/suggested-fixes.ts +0 -155
  120. package/src/core/exporter/case-study/index.ts +0 -270
  121. package/src/core/exporter/curl.ts +0 -40
  122. package/src/core/exporter/exporter.ts +0 -48
  123. package/src/core/exporter/html-report/escape.ts +0 -24
  124. package/src/core/exporter/html-report/index.ts +0 -479
  125. package/src/core/exporter/html-report/script.ts +0 -100
  126. package/src/core/exporter/html-report/styles.ts +0 -408
  127. package/src/core/generator/catalog-builder.ts +0 -179
  128. package/src/core/generator/chunker.ts +0 -78
  129. package/src/core/generator/coverage-phase.ts +0 -0
  130. package/src/core/generator/coverage-scanner.ts +0 -87
  131. package/src/core/generator/data-factory.ts +0 -759
  132. package/src/core/generator/describe.ts +0 -302
  133. package/src/core/generator/endpoint-warnings.ts +0 -52
  134. package/src/core/generator/fixtures-builder.ts +0 -332
  135. package/src/core/generator/index.ts +0 -14
  136. package/src/core/generator/openapi-reader.ts +0 -297
  137. package/src/core/generator/path-param-disambig.ts +0 -140
  138. package/src/core/generator/resources-builder.ts +0 -898
  139. package/src/core/generator/schema-utils.ts +0 -112
  140. package/src/core/generator/serializer.ts +0 -343
  141. package/src/core/generator/suite-generator.ts +0 -1301
  142. package/src/core/generator/types.ts +0 -63
  143. package/src/core/identity/identity-file.ts +0 -0
  144. package/src/core/lint/affects.ts +0 -28
  145. package/src/core/lint/config.ts +0 -96
  146. package/src/core/lint/format.ts +0 -42
  147. package/src/core/lint/index.ts +0 -94
  148. package/src/core/lint/reporter.ts +0 -128
  149. package/src/core/lint/rules/consistency.ts +0 -158
  150. package/src/core/lint/rules/heuristics.ts +0 -97
  151. package/src/core/lint/rules/strictness.ts +0 -109
  152. package/src/core/lint/types.ts +0 -96
  153. package/src/core/lint/walker.ts +0 -248
  154. package/src/core/meta/meta-store.ts +0 -11
  155. package/src/core/output/README.md +0 -73
  156. package/src/core/output/index.ts +0 -13
  157. package/src/core/output/run.ts +0 -91
  158. package/src/core/output/types.ts +0 -122
  159. package/src/core/parser/dynamic-values.ts +0 -160
  160. package/src/core/parser/env-interpolation.ts +0 -104
  161. package/src/core/parser/filter.ts +0 -97
  162. package/src/core/parser/schema.ts +0 -359
  163. package/src/core/parser/types.ts +0 -117
  164. package/src/core/parser/variables.ts +0 -0
  165. package/src/core/parser/yaml-parser.ts +0 -181
  166. package/src/core/probe/bootstrap.ts +0 -34
  167. package/src/core/probe/dry-run-envelope.ts +0 -61
  168. package/src/core/probe/mass-assignment/classify.ts +0 -175
  169. package/src/core/probe/mass-assignment/cleanup.ts +0 -52
  170. package/src/core/probe/mass-assignment/digest.ts +0 -114
  171. package/src/core/probe/mass-assignment/orchestrator.ts +0 -459
  172. package/src/core/probe/mass-assignment/regression.ts +0 -141
  173. package/src/core/probe/mass-assignment/suspects.ts +0 -92
  174. package/src/core/probe/mass-assignment/types.ts +0 -135
  175. package/src/core/probe/mass-assignment-probe-class.ts +0 -198
  176. package/src/core/probe/mass-assignment-probe.ts +0 -27
  177. package/src/core/probe/mass-assignment-template.ts +0 -240
  178. package/src/core/probe/method-probe.ts +0 -164
  179. package/src/core/probe/method-shared.ts +0 -69
  180. package/src/core/probe/negative-probe.ts +0 -691
  181. package/src/core/probe/orphan-tracker.ts +0 -188
  182. package/src/core/probe/path-discovery.ts +0 -439
  183. package/src/core/probe/probe-harness.ts +0 -119
  184. package/src/core/probe/registry.ts +0 -89
  185. package/src/core/probe/runner.ts +0 -136
  186. package/src/core/probe/security/baseline.ts +0 -174
  187. package/src/core/probe/security/classify.ts +0 -341
  188. package/src/core/probe/security/cleanup.ts +0 -125
  189. package/src/core/probe/security/detectors.ts +0 -71
  190. package/src/core/probe/security/digest.ts +0 -104
  191. package/src/core/probe/security/orchestrator.ts +0 -398
  192. package/src/core/probe/security/regression.ts +0 -103
  193. package/src/core/probe/security/types.ts +0 -151
  194. package/src/core/probe/security-probe-class.ts +0 -207
  195. package/src/core/probe/security-probe.ts +0 -32
  196. package/src/core/probe/shared.ts +0 -531
  197. package/src/core/probe/static-probe-class.ts +0 -125
  198. package/src/core/probe/types.ts +0 -165
  199. package/src/core/probe/verdict-aggregator.ts +0 -33
  200. package/src/core/probe/webhooks-probe.ts +0 -282
  201. package/src/core/reporter/console.ts +0 -240
  202. package/src/core/reporter/index.ts +0 -22
  203. package/src/core/reporter/json.ts +0 -22
  204. package/src/core/reporter/junit.ts +0 -93
  205. package/src/core/reporter/ndjson.ts +0 -37
  206. package/src/core/reporter/types.ts +0 -15
  207. package/src/core/runner/assertions.ts +0 -383
  208. package/src/core/runner/async-pool.ts +0 -108
  209. package/src/core/runner/auth-path.ts +0 -8
  210. package/src/core/runner/ci-context.ts +0 -72
  211. package/src/core/runner/executor.ts +0 -652
  212. package/src/core/runner/expr-eval.ts +0 -41
  213. package/src/core/runner/form-encode.ts +0 -41
  214. package/src/core/runner/http-client.ts +0 -224
  215. package/src/core/runner/learn-drift.ts +0 -293
  216. package/src/core/runner/preflight-vars.ts +0 -153
  217. package/src/core/runner/progress-tracker.ts +0 -73
  218. package/src/core/runner/rate-limiter.ts +0 -185
  219. package/src/core/runner/run-kind.ts +0 -45
  220. package/src/core/runner/schema-validator.ts +0 -308
  221. package/src/core/runner/send-request.ts +0 -232
  222. package/src/core/runner/transforms.ts +0 -65
  223. package/src/core/runner/types.ts +0 -94
  224. package/src/core/secrets/registry.ts +0 -164
  225. package/src/core/secrets/secrets-file.ts +0 -115
  226. package/src/core/selectors/operation-filter.ts +0 -144
  227. package/src/core/setup-api.ts +0 -590
  228. package/src/core/severity/category.ts +0 -94
  229. package/src/core/severity/index.ts +0 -58
  230. package/src/core/spec/infer-schema.ts +0 -102
  231. package/src/core/spec/layers.ts +0 -154
  232. package/src/core/spec/merge-specs.ts +0 -156
  233. package/src/core/spec/schema-from-runs.ts +0 -117
  234. package/src/core/spec/schema-overlay.ts +0 -130
  235. package/src/core/util/ajv.ts +0 -13
  236. package/src/core/util/format-eta.ts +0 -21
  237. package/src/core/util/headers.ts +0 -9
  238. package/src/core/util/url.ts +0 -24
  239. package/src/core/utils.ts +0 -13
  240. package/src/core/workspace/config.ts +0 -129
  241. package/src/core/workspace/fixture-gap-report.ts +0 -84
  242. package/src/core/workspace/fixture-gaps.ts +0 -71
  243. package/src/core/workspace/manifest.ts +0 -283
  244. package/src/core/workspace/output-rotation.ts +0 -62
  245. package/src/core/workspace/root.ts +0 -96
  246. package/src/core/workspace/triage-path.ts +0 -87
  247. package/src/db/lint-runs.ts +0 -47
  248. package/src/db/migrate.ts +0 -128
  249. package/src/db/migrations/0001_run_kind.sql +0 -25
  250. package/src/db/migrations/0002_run_kind_request.sql +0 -59
  251. package/src/db/migrations/sql.d.ts +0 -4
  252. package/src/db/queries/collections.ts +0 -133
  253. package/src/db/queries/coverage.ts +0 -9
  254. package/src/db/queries/dashboard.ts +0 -59
  255. package/src/db/queries/results.ts +0 -216
  256. package/src/db/queries/runs.ts +0 -289
  257. package/src/db/queries/sessions.ts +0 -42
  258. package/src/db/queries/settings.ts +0 -28
  259. package/src/db/queries/types.ts +0 -172
  260. package/src/db/queries.ts +0 -75
  261. package/src/db/schema.ts +0 -298
@@ -1,108 +0,0 @@
1
- /**
2
- * Single source of truth for `--json` output across all CLI commands.
3
- *
4
- * Every `--json` response carries the same envelope:
5
- *
6
- * { ok, command, data, warnings, errors, exit_code? }
7
- *
8
- * Commands construct the payload (`data`) and ask one of the helpers
9
- * below to render it. Don't `console.log(JSON.stringify(...))` ad-hoc
10
- * for `--json` paths — go through `printJson` / `writeEnvelope` so the
11
- * shape stays uniform (TASK-73, TASK-74, closed by TASK-184).
12
- *
13
- * TASK-296: errors[] is a list of `{code, message, details?}` so an
14
- * agent can route on `code` without parsing the human message. Helpers
15
- * accept either a bare `string` (auto-wrapped with code `unknown_error`)
16
- * or a structured `ZondError` to keep call sites short.
17
- */
18
-
19
- // TASK-295: types are derived from the zod schemas in `./json-schemas.ts`
20
- // so the published JSON Schema (docs/json-schema/) and the runtime types
21
- // can never drift. Edit the enum/object there, run `bun run schemas`,
22
- // commit the regenerated docs.
23
- import type { z } from "zod";
24
- import {
25
- ZondErrorCodeSchema,
26
- ZondErrorSchema,
27
- } from "./json-schemas.ts";
28
-
29
- export type ZondErrorCode = z.infer<typeof ZondErrorCodeSchema>;
30
- export type ZondError = z.infer<typeof ZondErrorSchema>;
31
-
32
- export interface JsonEnvelope<T = unknown> {
33
- ok: boolean;
34
- command: string;
35
- data: T;
36
- warnings: string[];
37
- errors: ZondError[];
38
- /** Exit code the process will return. Present on error envelopes so a
39
- * caller can read the taxonomy class without re-parsing $? from a shell
40
- * (see ZOND.md → "Exit codes"). */
41
- exit_code?: number;
42
- }
43
-
44
- /** Accept either a bare string (auto-coded `unknown_error`) or a fully-
45
- * structured `ZondError`. Lets us migrate ~100 call sites incrementally
46
- * without breaking the schema. */
47
- export type ErrorInput = string | ZondError;
48
-
49
- function normalizeErrors(errs: readonly ErrorInput[]): ZondError[] {
50
- return errs.map(e =>
51
- typeof e === "string" ? { code: "unknown_error" as const, message: e } : e,
52
- );
53
- }
54
-
55
- export function jsonOk<T>(command: string, data: T, warnings?: string[]): JsonEnvelope<T> {
56
- return { ok: true, command, data, warnings: warnings ?? [], errors: [] };
57
- }
58
-
59
- export function jsonError(
60
- command: string,
61
- errors: readonly ErrorInput[],
62
- warnings?: string[],
63
- exitCode = 2,
64
- ): JsonEnvelope<null> {
65
- return {
66
- ok: false,
67
- command,
68
- data: null,
69
- warnings: warnings ?? [],
70
- errors: normalizeErrors(errors),
71
- exit_code: exitCode,
72
- };
73
- }
74
-
75
- export function printJson(envelope: JsonEnvelope): void {
76
- process.stdout.write(JSON.stringify(envelope, null, 2) + "\n");
77
- }
78
-
79
- /** Convenience constructor: `zerr("env_missing", "base_url not set", { var: "base_url" })`. */
80
- export function zerr(code: ZondErrorCode, message: string, details?: Record<string, unknown>): ZondError {
81
- return details ? { code, message, details } : { code, message };
82
- }
83
-
84
- /** Discriminated-union result an action can hand back to {@link writeEnvelope}. */
85
- export type EnvelopeResult<T> =
86
- | { ok: true; data: T; warnings?: string[] }
87
- | { ok: false; errors: readonly ErrorInput[]; warnings?: string[]; exitCode?: number };
88
-
89
- /**
90
- * Render a typed `EnvelopeResult` to stdout as a JSON envelope and return
91
- * the process exit code (0 on ok, `result.exitCode ?? 2` on error). This
92
- * is the recommended wrapper for new commands — it lets the handler
93
- * focus on producing a payload and surfaces the right exit code in one
94
- * call:
95
- *
96
- * const result = await doWork();
97
- * if (options.json) return writeEnvelope("my-cmd", result);
98
- * // …human path…
99
- */
100
- export function writeEnvelope<T>(command: string, result: EnvelopeResult<T>): number {
101
- if (result.ok) {
102
- printJson(jsonOk(command, result.data, result.warnings));
103
- return 0;
104
- }
105
- const exit = result.exitCode ?? 2;
106
- printJson(jsonError(command, result.errors, result.warnings, exit));
107
- return exit;
108
- }
@@ -1,314 +0,0 @@
1
- /**
2
- * TASK-295: zod sources of truth for the `--json` envelope shape and its
3
- * sub-types. Run `bun run scripts/emit-json-schemas.ts` after changing
4
- * any of these to regenerate `docs/json-schema/*.schema.json`.
5
- *
6
- * Why zod first, JSON Schema second: zod is the type AND the validator
7
- * we already ship; emitting JSON Schema from it keeps the published
8
- * schema and the runtime checks in lock-step. New fields land here and
9
- * propagate, instead of drifting between two hand-maintained shapes.
10
- */
11
-
12
- import { z } from "zod";
13
-
14
- /** TASK-296 closed enum — must stay in sync with `ZondErrorCode` in
15
- * `src/cli/json-envelope.ts`. */
16
- export const ZondErrorCodeSchema = z.enum([
17
- "unknown_error",
18
- "env_missing",
19
- "fixture_missing",
20
- "network_timeout",
21
- "network_error",
22
- "sandbox_blocked",
23
- "spec_load_failure",
24
- "yaml_parse_error",
25
- "workspace_not_found",
26
- "file_not_found",
27
- "permission_denied",
28
- "argument_invalid",
29
- "api_not_registered",
30
- "db_error",
31
- "auth_config_error",
32
- ]);
33
-
34
- export const ZondErrorSchema = z.object({
35
- code: ZondErrorCodeSchema,
36
- message: z.string(),
37
- details: z.record(z.string(), z.unknown()).optional(),
38
- });
39
-
40
- /** TASK-294 closed enum — must stay in sync with `RecommendedAction` in
41
- * `src/core/diagnostics/failure-hints.ts` and the per-check mapping in
42
- * `src/core/checks/recommended-action.ts` (ARV-11).
43
- * ARV-11 added three values for the depth-checks framework:
44
- * - `tighten_validation` — server accepted invalid input.
45
- * - `add_required_header` — server didn't enforce a required header.
46
- * - `wontfix_known_limitation` — known/accepted gap; agent should
47
- * not retry or report. */
48
- export const RecommendedActionSchema = z.enum([
49
- "report_backend_bug",
50
- "fix_auth_config",
51
- "fix_test_logic",
52
- "fix_network_config",
53
- "fix_env",
54
- "fix_spec",
55
- "fix_fixture",
56
- // ARV-42 — re-run `zond generate` for failures rooted in generator-emitted
57
- // bodies; editing the YAML directly is overwritten by the next regenerate.
58
- "regenerate_suite",
59
- "tighten_validation",
60
- "add_required_header",
61
- "wontfix_known_limitation",
62
- ]);
63
-
64
- /** Envelope body. `data` is open (`unknown`) so this schema covers every
65
- * command without enumerating each payload — command-specific schemas
66
- * can refine `data` per-command in a follow-up. */
67
- export const JsonEnvelopeSchema = z.object({
68
- ok: z.boolean(),
69
- command: z.string(),
70
- data: z.unknown(),
71
- warnings: z.array(z.string()),
72
- errors: z.array(ZondErrorSchema),
73
- exit_code: z.number().int().optional(),
74
- });
75
-
76
- /** ARV-1 (m-15): shape of `data` for `zond checks run --json`. The
77
- * envelope itself stays the generic JsonEnvelopeSchema; this schema
78
- * pins the per-command payload so agents can validate findings without
79
- * parsing them by-hand. ARV-11 adds `recommended_action` as a closed
80
- * enum on each finding. */
81
- export const SeveritySchema = z.enum(["critical", "high", "medium", "low", "info"]);
82
- export const CategorySchema = z.enum(["security", "reliability", "contract", "hygiene"]);
83
-
84
- export const CheckFindingSchema = z.object({
85
- check: z.string(),
86
- severity: SeveritySchema,
87
- // ARV-251: category drives per-section roll-up. Optional on the wire
88
- // for backwards compat with older NDJSON streams — derived by reader
89
- // from check id if absent.
90
- category: CategorySchema.optional(),
91
- operation: z.object({
92
- path: z.string(),
93
- method: z.string(),
94
- operationId: z.string().optional(),
95
- }),
96
- request_signature: z.string(),
97
- response_summary: z.object({
98
- status: z.number().int(),
99
- content_type: z.string().optional(),
100
- }),
101
- message: z.string(),
102
- evidence: z.record(z.string(), z.unknown()).optional(),
103
- // ARV-11: recommended_action is now a closed enum so agents can
104
- // route on it without parsing free-form strings. Same enum used by
105
- // `db diagnose` (TASK-294) plus three depth-check additions.
106
- recommended_action: RecommendedActionSchema.optional(),
107
- });
108
-
109
- export const CheckRunSummarySchema = z.object({
110
- operations: z.number().int().nonnegative(),
111
- cases: z.number().int().nonnegative(),
112
- checks_run: z.number().int().nonnegative(),
113
- findings: z.number().int().nonnegative(),
114
- by_severity: z.object({
115
- critical: z.number().int().nonnegative(),
116
- high: z.number().int().nonnegative(),
117
- medium: z.number().int().nonnegative(),
118
- low: z.number().int().nonnegative(),
119
- info: z.number().int().nonnegative(),
120
- }),
121
- by_category: z.object({
122
- security: z.number().int().nonnegative(),
123
- reliability: z.number().int().nonnegative(),
124
- contract: z.number().int().nonnegative(),
125
- hygiene: z.number().int().nonnegative(),
126
- }),
127
- // ARV-26: per-(check, reason) skip tally — surfaces probe outcomes that
128
- // never produced a checkable response (e.g. probe got 4xx, schema only on
129
- // 200) so "0 findings" doesn't read as "all green".
130
- skipped_outcomes: z.record(z.string(), z.number().int().nonnegative()),
131
- // ARV-83: structured counterpart to skipped_outcomes — split into
132
- // {check, reason, count} so consumers don't have to colon-tokenise a
133
- // reason that may itself contain colons. Sorted by count desc.
134
- skipped_outcomes_grouped: z.array(z.object({
135
- check: z.string(),
136
- reason: z.string(),
137
- count: z.number().int().nonnegative(),
138
- })),
139
- // ARV-283 / ARV-68: count of findings the severity matrix demoted to
140
- // `info-suppressed`. Excluded from `findings` / `by_severity` so CI
141
- // gates ignore them, but exposed here so consumers (ajv validators
142
- // included) accept the field — the runner emits it unconditionally.
143
- suppressed: z.number().int().nonnegative().optional(),
144
- });
145
-
146
- /** ARV-60: spec-level rollup row. Emitted when ≥80% of a check's
147
- * applicable operations share the same root cause (status drift,
148
- * missing-declaration skip cluster, or no-detector zero-case). Lives in
149
- * `data.spec_findings` and as its own `spec_finding` NDJSON event. */
150
- export const SpecFindingSchema = z.object({
151
- check: z.string(),
152
- kind: z.enum(["status_drift", "missing_declaration", "no_detector", "broken_baseline", "other"]),
153
- severity: SeveritySchema,
154
- category: CategorySchema.optional(),
155
- reason: z.string(),
156
- fix_hint: z.string(),
157
- affected_operations: z.array(z.object({
158
- path: z.string(),
159
- method: z.string(),
160
- operationId: z.string().optional(),
161
- })),
162
- count: z.number().int().nonnegative(),
163
- applicable: z.number().int().nonnegative(),
164
- });
165
-
166
- export const ChecksRunDataSchema = z.object({
167
- findings: z.array(CheckFindingSchema),
168
- summary: CheckRunSummarySchema,
169
- // ARV-60: always present (empty array when no clusters cross 80%).
170
- spec_findings: z.array(SpecFindingSchema),
171
- });
172
-
173
- /** ARV-10 (m-15): NDJSON streaming events emitted by `zond checks run
174
- * --ndjson`. Each event is a snapshot JSON line on stdout — agents pipe
175
- * the stream into `jq` / a validator and consume findings as they happen
176
- * rather than waiting for the run to finish. The discriminated union
177
- * below is the schema we publish — every emitted line MUST match one
178
- * branch exactly (verified by ajv in tests). */
179
- const OperationRefSchema = z.object({
180
- path: z.string(),
181
- method: z.string(),
182
- operationId: z.string().optional(),
183
- });
184
-
185
- export const NdjsonCheckStartEventSchema = z.object({
186
- type: z.literal("check_start"),
187
- ts: z.string(),
188
- operation: OperationRefSchema,
189
- });
190
-
191
- export const NdjsonCheckResultEventSchema = z.object({
192
- type: z.literal("check_result"),
193
- ts: z.string(),
194
- check: z.string(),
195
- // ARV-215: severity from the registry (mirrors `zond checks list`
196
- // [high|medium|low]). Lets consumers group NDJSON by severity without
197
- // re-joining against the registry.
198
- severity: z.enum(["info", "low", "medium", "high", "critical"]),
199
- verdict: z.enum(["pass", "fail"]),
200
- operation: OperationRefSchema,
201
- request_signature: z.string(),
202
- response: z.object({
203
- status: z.number().int(),
204
- content_type: z.string().optional(),
205
- }),
206
- });
207
-
208
- export const NdjsonFindingEventSchema = z.object({
209
- type: z.literal("finding"),
210
- ts: z.string(),
211
- // ARV-156: mirror the top-level `check` field carried by check_start /
212
- // check_result so consumer pipelines can `jq -c '.check'` uniformly
213
- // across event types without branching on `.type`. The same value lives
214
- // inside `.finding.check` — existing consumers reading the nested form
215
- // keep working (back-compat addition, not a rename).
216
- check: z.string(),
217
- finding: CheckFindingSchema,
218
- });
219
-
220
- export const NdjsonSummaryEventSchema = z.object({
221
- type: z.literal("summary"),
222
- ts: z.string(),
223
- summary: CheckRunSummarySchema,
224
- });
225
-
226
- /** ARV-60: rolled-up spec-level finding event. Emitted before the
227
- * terminal `summary` event so streaming consumers see clusters in the
228
- * same order the CLI renders them. Per-op `finding` events are NOT
229
- * removed — both layers coexist. */
230
- export const NdjsonSpecFindingEventSchema = z.object({
231
- type: z.literal("spec_finding"),
232
- ts: z.string(),
233
- check: z.string(),
234
- spec_finding: SpecFindingSchema,
235
- });
236
-
237
- export const NdjsonEventSchema = z.discriminatedUnion("type", [
238
- NdjsonCheckStartEventSchema,
239
- NdjsonCheckResultEventSchema,
240
- NdjsonFindingEventSchema,
241
- NdjsonSpecFindingEventSchema,
242
- NdjsonSummaryEventSchema,
243
- ]);
244
-
245
- /** m-17 / ARV-50: shape of `data` for `zond probe <class> --dry-run --json`.
246
- * Severity is intentionally absent — nothing is classified yet, so
247
- * reusing the run-time bucket would mislead CI gates (F1-15). The
248
- * `skip_reason` enum is open across probe families (e.g. security has
249
- * `isolated-protected`, mass-assignment has its own subset); we keep
250
- * it as a string with documented values rather than a closed enum
251
- * that needs to be rev'd every time a new class lands. */
252
- export const ProbeEndpointPlanSchema = z.object({
253
- path: z.string(),
254
- method: z.string(),
255
- planned: z.boolean(),
256
- classes_planned: z.array(z.string()),
257
- fields_planned: z.array(z.string()),
258
- skip_reason: z.string().nullable(),
259
- });
260
-
261
- export const ProbeDryRunDataSchema = z.object({
262
- endpoints: z.array(ProbeEndpointPlanSchema),
263
- summary: z.object({
264
- totalEndpoints: z.number().int().nonnegative(),
265
- planned: z.number().int().nonnegative(),
266
- skipped: z.number().int().nonnegative(),
267
- }),
268
- });
269
-
270
- /** m-17 / ARV-51: shape of `data` for live probe runs (`zond probe <class>
271
- * --report json` or the default `--json`). One entry per endpoint with
272
- * structured findings — no markdown blob. The legacy `data.digest.stdout`
273
- * field is gone (F3-15 / F4-15). */
274
- export const ProbeFindingSchema = z.object({
275
- class: z.string(),
276
- severity: z.enum(["high", "low", "inconclusive", "ok"]),
277
- evidence: z.record(z.string(), z.unknown()),
278
- });
279
-
280
- export const ProbeEndpointResultSchema = z.object({
281
- path: z.string(),
282
- method: z.string(),
283
- classes_run: z.array(z.string()),
284
- findings: z.array(ProbeFindingSchema),
285
- status: z.enum(["ok", "high", "low", "inconclusive", "skipped"]),
286
- skip_reason: z.string().optional(),
287
- });
288
-
289
- export const ProbeRunDataSchema = z.object({
290
- endpoints: z.array(ProbeEndpointResultSchema),
291
- summary: z.object({
292
- totalEndpoints: z.number().int().nonnegative(),
293
- probed: z.number().int().nonnegative(),
294
- by_status: z.object({
295
- ok: z.number().int().nonnegative(),
296
- high: z.number().int().nonnegative(),
297
- low: z.number().int().nonnegative(),
298
- inconclusive: z.number().int().nonnegative(),
299
- skipped: z.number().int().nonnegative(),
300
- }),
301
- }),
302
- });
303
-
304
- export const SCHEMAS = {
305
- envelope: JsonEnvelopeSchema,
306
- error: ZondErrorSchema,
307
- errorCode: ZondErrorCodeSchema,
308
- recommendedAction: RecommendedActionSchema,
309
- checksRunData: ChecksRunDataSchema,
310
- checkFinding: CheckFindingSchema,
311
- "ndjson-events": NdjsonEventSchema,
312
- probeDryRun: ProbeDryRunDataSchema,
313
- probeRun: ProbeRunDataSchema,
314
- } as const;
package/src/cli/output.ts DELETED
@@ -1,40 +0,0 @@
1
- const RESET = "\x1b[0m";
2
- const RED = "\x1b[31m";
3
- const GREEN = "\x1b[32m";
4
- const YELLOW = "\x1b[33m";
5
-
6
- function useColor(): boolean {
7
- return process.stderr.isTTY ?? false;
8
- }
9
-
10
- let debugHintShown = false;
11
-
12
- // ARV-203: when a command catches an unexpected throw and calls
13
- // `printError(msg, err)`, gate the stack trace behind ZOND_DEBUG=1.
14
- // Without the env var, append a one-time hint so the user knows the
15
- // switch exists — the previous behaviour silently dropped TypeError
16
- // stacks and forced reverse-engineering from the bare message.
17
- export function printError(message: string, err?: unknown): void {
18
- const msg = useColor() ? `${RED}Error: ${message}${RESET}` : `Error: ${message}`;
19
- process.stderr.write(msg + "\n");
20
- if (err === undefined) return;
21
- if (process.env.ZOND_DEBUG === "1" && err instanceof Error && err.stack) {
22
- process.stderr.write(err.stack + "\n");
23
- return;
24
- }
25
- if (!debugHintShown) {
26
- debugHintShown = true;
27
- process.stderr.write(" hint: set ZOND_DEBUG=1 to print the full stack trace.\n");
28
- }
29
- }
30
-
31
- export function printSuccess(message: string): void {
32
- const color = process.stdout.isTTY ?? false;
33
- const msg = color ? `${GREEN}${message}${RESET}` : message;
34
- process.stdout.write(msg + "\n");
35
- }
36
-
37
- export function printWarning(message: string): void {
38
- const msg = useColor() ? `${YELLOW}Warning: ${message}${RESET}` : `Warning: ${message}`;
39
- process.stderr.write(msg + "\n");
40
- }
@@ -1,219 +0,0 @@
1
- import { Command } from "commander";
2
-
3
- import { registerRun } from "./commands/run.ts";
4
- import { registerCheck, registerLint } from "./commands/check.ts";
5
- import { registerChecks } from "./commands/checks.ts";
6
- import { registerCoverage } from "./commands/coverage.ts";
7
- import { registerCi } from "./commands/ci-init.ts";
8
- import { registerClean } from "./commands/clean.ts";
9
- import { registerCleanup } from "./commands/cleanup.ts";
10
- import { registerInit } from "./commands/init/index.ts";
11
- import { registerDescribe } from "./commands/describe.ts";
12
- import { registerDb } from "./commands/db.ts";
13
- import { registerRequest } from "./commands/request.ts";
14
- import { registerGenerate } from "./commands/generate.ts";
15
- import { registerPrepareFixtures } from "./commands/prepare-fixtures.ts";
16
- import { registerFixtures } from "./commands/fixtures.ts";
17
- import { registerSecrets } from "./commands/secrets.ts";
18
- import { registerProbes } from "./commands/probe.ts";
19
- import { bootstrapProbes } from "../core/probe/bootstrap.ts";
20
- import { registerReport } from "./commands/report.ts";
21
- import { registerCatalog } from "./commands/catalog.ts";
22
- import { registerCompletions } from "./commands/completions.ts";
23
- import { registerUse } from "./commands/use.ts";
24
- import { registerSession } from "./commands/session.ts";
25
- import { registerDoctor } from "./commands/doctor.ts";
26
- import { registerRefreshApi } from "./commands/refresh-api.ts";
27
- import { registerSchemaFromRuns } from "./commands/schema-from-runs.ts";
28
- import { registerAdd } from "./commands/add-api.ts";
29
- import { registerRemove } from "./commands/remove-api.ts";
30
- import { registerAudit } from "./commands/audit.ts";
31
- import { registerReference } from "./commands/reference.ts";
32
- import { registerApiAnnotate } from "./commands/api/annotate/index.ts";
33
-
34
- import { getSecretRegistry } from "../core/secrets/registry.ts";
35
- import { getRuntimeInfo } from "./runtime.ts";
36
- import { VERSION } from "./version.ts";
37
- import { preprocessArgv } from "./argv.ts";
38
-
39
- export { preprocessArgv };
40
-
41
- // ── Program builder ──
42
-
43
- export function buildProgram(): Command {
44
- const program = new Command("zond")
45
- .description("API Testing Platform")
46
- .version(`${VERSION} (${getRuntimeInfo()})`, "-v, --version", "Show version")
47
- .helpOption("-h, --help", "Show this help")
48
- .showHelpAfterError("(run 'zond --help' for usage)")
49
- .exitOverride()
50
- // TASK-166 (m-10): global escape hatch for local debugging — disables
51
- // the secret registry's redaction pass everywhere (DB writes,
52
- // exporters, stdout). Default is redact-on. Hook is read from the
53
- // env var so it survives across nested subcommand parsers.
54
- .option("--no-redact", "Disable auto-redaction of registered secret values (debug only)")
55
- .option(
56
- "--api <name>",
57
- "TASK-290: Select the active API for this invocation. Resolution order: per-command --api > global --api (this flag) > ZOND_API env > .zond/current-api file (set via `zond use <name>`).",
58
- )
59
- .hook("preAction", (thisCommand) => {
60
- const enabled = thisCommand.opts().redact !== false;
61
- // Mirror the flag into env so deeply-nested code that doesn't have
62
- // access to `cmd` (e.g. setup-api, exporters) can still consult it.
63
- process.env.ZOND_REDACT = enabled ? "1" : "0";
64
- getSecretRegistry().setEnabled(enabled);
65
- // TASK-290: mirror the global --api flag into env so the resolution
66
- // chain in core/context/current.ts (which has no `cmd` ref) sees it.
67
- // Per-command --api still wins because it is passed positionally to
68
- // resolveSpecArg / resolveApiCollection.
69
- const apiGlobal = thisCommand.opts().api;
70
- if (typeof apiGlobal === "string" && apiGlobal.length > 0) {
71
- process.env.ZOND_API_GLOBAL = apiGlobal;
72
- } else {
73
- delete process.env.ZOND_API_GLOBAL;
74
- }
75
- });
76
-
77
- registerRun(program);
78
-
79
- registerCheck(program);
80
- registerChecks(program);
81
- registerLint(program);
82
-
83
- registerCi(program);
84
-
85
- registerUse(program);
86
- registerRefreshApi(program);
87
- registerSchemaFromRuns(program);
88
- registerDoctor(program);
89
-
90
- registerSession(program);
91
- registerCoverage(program);
92
-
93
- registerInit(program);
94
- registerAdd(program);
95
- registerRemove(program);
96
-
97
- registerDescribe(program);
98
- registerDb(program);
99
- registerRequest(program);
100
-
101
- registerClean(program);
102
- registerCleanup(program);
103
-
104
- registerGenerate(program);
105
- registerPrepareFixtures(program);
106
- registerFixtures(program);
107
- registerSecrets(program);
108
- registerAudit(program);
109
-
110
- // m-17 / ARV-49: validate registered probes implement the Probe
111
- // contract before commander gets to wire them up. Boot-throws on a
112
- // missing slot, so a regression can't slip past CI.
113
- bootstrapProbes();
114
- registerProbes(program);
115
-
116
- registerCatalog(program);
117
- registerReport(program);
118
-
119
- registerCompletions(program);
120
- registerReference(program);
121
- registerApiAnnotate(program);
122
-
123
- // TASK-267: group top-level commands by phase in `zond --help`. Without
124
- // grouping, the flat 20+ command list buries the workflow shape; with it,
125
- // a new tester can see "setup → generate → run → analyze → report" at a
126
- // glance. Commands not listed below stay in the default group.
127
- const HELP_GROUPS: Record<string, string> = {
128
- // setup: register an API, prepare workspace
129
- "init": "Setup:",
130
- "add": "Setup:",
131
- "remove": "Setup:",
132
- "use": "Setup:",
133
- "secrets": "Setup:",
134
- "refresh-api": "Setup:",
135
- "doctor": "Setup:",
136
- "clean": "Setup:",
137
- "cleanup": "Setup:",
138
- // generate: produce suites/probes from the spec
139
- "generate": "Generate:",
140
- "prepare-fixtures": "Generate:",
141
- "probe": "Generate:",
142
- // run: execute suites against a live API
143
- "run": "Run:",
144
- "session": "Run:",
145
- "request": "Run:",
146
- // analyze: post-run inspection and triage
147
- "coverage": "Analyze:",
148
- "db": "Analyze:",
149
- "audit": "Analyze:",
150
- "check": "Analyze:",
151
- "checks": "Analyze:",
152
- "describe": "Analyze:",
153
- // report: outbound artefacts (HTML, bundles, catalog)
154
- "report": "Report:",
155
- "catalog": "Report:",
156
- // other: scaffolding / shell integration
157
- "ci": "Other:",
158
- "completions": "Other:",
159
- "reference": "Other:",
160
- };
161
- for (const sub of program.commands) {
162
- const group = HELP_GROUPS[sub.name()];
163
- if (group) sub.helpGroup(group);
164
- }
165
-
166
- // TASK-73: previously `--json` was a top-level/global option that propagated
167
- // to every subcommand, which collided with `run --report json` (and broke
168
- // `run --json` outright). Now it is per-command. Attach `--json` to every
169
- // subcommand that previously read it via globalJson(), EXCEPT `run` —
170
- // run's only JSON output path is `--report json`.
171
- // Skip by fully-qualified path so `db run` (inner) keeps --json while
172
- // top-level `run` does not.
173
- const skipJson = new Set(["run", "completions"]);
174
- const attachJson = (cmd: Command, parentPath: string): void => {
175
- const path = parentPath ? `${parentPath} ${cmd.name()}` : cmd.name();
176
- // Only leaf commands (those with action handlers) get --json — parent
177
- // namespace commands like `db` and `ci` would otherwise shadow the option
178
- // on their children and `cmd.opts()` on the leaf would not see --json.
179
- const hasAction = (cmd as unknown as { _actionHandler?: unknown })._actionHandler != null;
180
- if (hasAction && !skipJson.has(path)) {
181
- cmd.option(
182
- "--json",
183
- "Emit a `{ok, command, data, warnings, errors}` envelope on stdout. " +
184
- "Distinct from `zond run --report json` (which is a per-test test-run report).",
185
- );
186
- }
187
- for (const sub of cmd.commands) attachJson(sub, path);
188
- };
189
- for (const sub of program.commands) attachJson(sub, "");
190
-
191
- // TASK-297: stamp every leaf with a "related skill" footer so `zond <cmd>
192
- // --help` is a single-stop entry point for an agent: discover the flag
193
- // surface AND know which skill file to open for the workflow context.
194
- // Mapped by fully-qualified path; `*` matches any unnamed leaf and is
195
- // tried last.
196
- const skillFor: Record<string, string> = {
197
- // Depth-check & probe commands → checks skill (annotate flow + m-20).
198
- "checks run": "skills/zond-checks.md",
199
- "checks list": "skills/zond-checks.md",
200
- "api annotate": "skills/zond-checks.md",
201
- "probe security": "skills/zond-checks.md",
202
- "probe mass-assignment": "skills/zond-checks.md",
203
- // Triage-class commands.
204
- "db diagnose": "skills/zond-triage.md",
205
- "db compare": "skills/zond-triage.md",
206
- };
207
- const attachHelp = (cmd: Command, parentPath: string): void => {
208
- const path = parentPath ? `${parentPath} ${cmd.name()}` : cmd.name();
209
- const hasAction = (cmd as unknown as { _actionHandler?: unknown })._actionHandler != null;
210
- if (hasAction) {
211
- const skill = skillFor[path] ?? "skills/zond.md";
212
- cmd.addHelpText("after", `\nRelated skill: ${skill}`);
213
- }
214
- for (const sub of cmd.commands) attachHelp(sub, path);
215
- };
216
- for (const sub of program.commands) attachHelp(sub, "");
217
-
218
- return program;
219
- }