Skip to main content

provenant/output_schema/
metadata.rs

1// SPDX-FileCopyrightText: Provenant contributors
2// SPDX-License-Identifier: Apache-2.0
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct OutputTypeDoc {
6    pub type_name: &'static str,
7    pub json_paths: &'static [&'static str],
8    pub summary: &'static str,
9    pub fields: &'static [OutputFieldDoc],
10}
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct OutputFieldDoc {
14    pub json_name: &'static str,
15    pub rust_field: &'static str,
16    pub value_shape: &'static str,
17    pub presence: &'static str,
18    pub meaning: &'static str,
19}
20
21const OUTPUT_FIELDS: &[OutputFieldDoc] = &[
22    OutputFieldDoc {
23        json_name: "summary",
24        rust_field: "summary",
25        value_shape: "object",
26        presence: "Emitted only when available.",
27        meaning: "Codebase-level rollup derived during post-processing.",
28    },
29    OutputFieldDoc {
30        json_name: "tallies",
31        rust_field: "tallies",
32        value_shape: "object",
33        presence: "Emitted only when tally generation is enabled.",
34        meaning: "Count-oriented rollup across the full scan result.",
35    },
36    OutputFieldDoc {
37        json_name: "tallies_of_key_files",
38        rust_field: "tallies_of_key_files",
39        value_shape: "object",
40        presence: "Emitted only when key-file tallies are available.",
41        meaning: "Tally rollup restricted to files treated as key files for summary scoring.",
42    },
43    OutputFieldDoc {
44        json_name: "tallies_by_facet",
45        rust_field: "tallies_by_facet",
46        value_shape: "array<object>",
47        presence: "Emitted only when facet tallies were requested.",
48        meaning: "Facet-scoped tally output for user-defined facet groupings.",
49    },
50    OutputFieldDoc {
51        json_name: "headers",
52        rust_field: "headers",
53        value_shape: "array<object>",
54        presence: "Always emitted.",
55        meaning: "Per-run metadata blocks describing tool/version/options and scan environment.",
56    },
57    OutputFieldDoc {
58        json_name: "packages",
59        rust_field: "packages",
60        value_shape: "array<object>",
61        presence: "Always emitted.",
62        meaning: "Assembled top-level package records visible on the public output contract.",
63    },
64    OutputFieldDoc {
65        json_name: "dependencies",
66        rust_field: "dependencies",
67        value_shape: "array<object>",
68        presence: "Always emitted.",
69        meaning: "Top-level dependency records emitted after assembly and hoisting.",
70    },
71    OutputFieldDoc {
72        json_name: "license_detections",
73        rust_field: "license_detections",
74        value_shape: "array<object>",
75        presence: "Always emitted.",
76        meaning: "Top-level grouped license detections across the scanned codebase.",
77    },
78    OutputFieldDoc {
79        json_name: "files",
80        rust_field: "files",
81        value_shape: "array<object>",
82        presence: "Always emitted.",
83        meaning: "File and directory records with the main per-resource findings surface.",
84    },
85    OutputFieldDoc {
86        json_name: "license_references",
87        rust_field: "license_references",
88        value_shape: "array<object>",
89        presence: "Always emitted.",
90        meaning: "Top-level unique license reference blocks for emitted detections.",
91    },
92    OutputFieldDoc {
93        json_name: "license_rule_references",
94        rust_field: "license_rule_references",
95        value_shape: "array<object>",
96        presence: "Always emitted.",
97        meaning: "Top-level unique rule reference blocks for emitted detections.",
98    },
99];
100
101const HEADER_FIELDS: &[OutputFieldDoc] = &[
102    OutputFieldDoc {
103        json_name: "tool_name",
104        rust_field: "tool_name",
105        value_shape: "string",
106        presence: "Always emitted.",
107        meaning: "Scanner tool name recorded for the run.",
108    },
109    OutputFieldDoc {
110        json_name: "tool_version",
111        rust_field: "tool_version",
112        value_shape: "string",
113        presence: "Always emitted.",
114        meaning: "Scanner version recorded for the run.",
115    },
116    OutputFieldDoc {
117        json_name: "options",
118        rust_field: "options",
119        value_shape: "object",
120        presence: "Always emitted.",
121        meaning: "Serialized scan options so downstream readers can interpret how the run was performed.",
122    },
123    OutputFieldDoc {
124        json_name: "notice",
125        rust_field: "notice",
126        value_shape: "string",
127        presence: "Always emitted.",
128        meaning: "Run-level legal or attribution notice emitted by the scanner.",
129    },
130    OutputFieldDoc {
131        json_name: "start_timestamp",
132        rust_field: "start_timestamp",
133        value_shape: "string",
134        presence: "Always emitted.",
135        meaning: "Run start timestamp.",
136    },
137    OutputFieldDoc {
138        json_name: "end_timestamp",
139        rust_field: "end_timestamp",
140        value_shape: "string",
141        presence: "Always emitted.",
142        meaning: "Run end timestamp.",
143    },
144    OutputFieldDoc {
145        json_name: "output_format_version",
146        rust_field: "output_format_version",
147        value_shape: "string",
148        presence: "Always emitted.",
149        meaning: "Version of the public output format contract used by this run.",
150    },
151    OutputFieldDoc {
152        json_name: "duration",
153        rust_field: "duration",
154        value_shape: "number",
155        presence: "Always emitted.",
156        meaning: "Wall-clock scan duration recorded for the run.",
157    },
158    OutputFieldDoc {
159        json_name: "errors",
160        rust_field: "errors",
161        value_shape: "array<string>",
162        presence: "Always emitted.",
163        meaning: "Run-level errors recorded in the header rather than on a specific file.",
164    },
165    OutputFieldDoc {
166        json_name: "warnings",
167        rust_field: "warnings",
168        value_shape: "array<string>",
169        presence: "Always emitted.",
170        meaning: "Run-level warnings recorded in the header rather than on a specific file.",
171    },
172    OutputFieldDoc {
173        json_name: "extra_data",
174        rust_field: "extra_data",
175        value_shape: "object",
176        presence: "Always emitted.",
177        meaning: "Scanner-owned counts and provenance metadata that augment the header contract.",
178    },
179];
180
181const EXTRA_DATA_FIELDS: &[OutputFieldDoc] = &[
182    OutputFieldDoc {
183        json_name: "spdx_license_list_version",
184        rust_field: "spdx_license_list_version",
185        value_shape: "string",
186        presence: "Always emitted.",
187        meaning: "The SPDX license list version associated with the effective license data used for the run.",
188    },
189    OutputFieldDoc {
190        json_name: "files_count",
191        rust_field: "files_count",
192        value_shape: "integer",
193        presence: "Always emitted.",
194        meaning: "Count of file records seen by the scan pipeline.",
195    },
196    OutputFieldDoc {
197        json_name: "directories_count",
198        rust_field: "directories_count",
199        value_shape: "integer",
200        presence: "Always emitted.",
201        meaning: "Count of directory records seen by the scan pipeline.",
202    },
203    OutputFieldDoc {
204        json_name: "excluded_count",
205        rust_field: "excluded_count",
206        value_shape: "integer",
207        presence: "Always emitted.",
208        meaning: "Count of paths excluded before file processing completed.",
209    },
210    OutputFieldDoc {
211        json_name: "license_index_provenance",
212        rust_field: "license_index_provenance",
213        value_shape: "object",
214        presence: "Emitted only when index provenance is available.",
215        meaning: "Provenance metadata for the effective embedded or custom license index used during detection.",
216    },
217];
218
219const SUMMARY_FIELDS: &[OutputFieldDoc] = &[
220    OutputFieldDoc {
221        json_name: "declared_license_expression",
222        rust_field: "declared_license_expression",
223        value_shape: "string",
224        presence: "Emitted only when the summary can derive a declared expression.",
225        meaning: "Best summary-level declared license rollup derived from key files and assembled package data.",
226    },
227    OutputFieldDoc {
228        json_name: "license_clarity_score",
229        rust_field: "license_clarity_score",
230        value_shape: "object",
231        presence: "Emitted only when clarity scoring is available.",
232        meaning: "Structured clarity signal explaining how complete and trustworthy the summary-level licensing evidence looks.",
233    },
234    OutputFieldDoc {
235        json_name: "other_license_expressions",
236        rust_field: "other_license_expressions",
237        value_shape: "array<object>",
238        presence: "Emitted only when non-empty.",
239        meaning: "Secondary license expressions that contributed to the summary but were not chosen as the primary declared expression.",
240    },
241    OutputFieldDoc {
242        json_name: "other_holders",
243        rust_field: "other_holders",
244        value_shape: "array<object>",
245        presence: "Emitted only when non-empty.",
246        meaning: "Secondary holders that contributed to the summary but were not chosen as the primary holder.",
247    },
248    OutputFieldDoc {
249        json_name: "other_languages",
250        rust_field: "other_languages",
251        value_shape: "array<object>",
252        presence: "Emitted only when non-empty.",
253        meaning: "Secondary languages that contributed to the summary but were not chosen as the primary language.",
254    },
255];
256
257const FILE_INFO_FIELDS: &[OutputFieldDoc] = &[
258    OutputFieldDoc {
259        json_name: "path",
260        rust_field: "path",
261        value_shape: "string",
262        presence: "Always emitted.",
263        meaning: "Scan-root-relative path for the file or directory record.",
264    },
265    OutputFieldDoc {
266        json_name: "type",
267        rust_field: "file_type",
268        value_shape: "string",
269        presence: "Always emitted.",
270        meaning: "File-vs-directory type discriminator on the public output surface.",
271    },
272    OutputFieldDoc {
273        json_name: "name",
274        rust_field: "name",
275        value_shape: "string",
276        presence: "Always emitted.",
277        meaning: "Basename of the file or directory record.",
278    },
279    OutputFieldDoc {
280        json_name: "base_name",
281        rust_field: "base_name",
282        value_shape: "string",
283        presence: "Always emitted.",
284        meaning: "Basename without extension.",
285    },
286    OutputFieldDoc {
287        json_name: "extension",
288        rust_field: "extension",
289        value_shape: "string",
290        presence: "Always emitted.",
291        meaning: "Filename extension including the leading dot when one exists.",
292    },
293    OutputFieldDoc {
294        json_name: "size",
295        rust_field: "size",
296        value_shape: "integer",
297        presence: "Always emitted.",
298        meaning: "File size in bytes for files, or zero for synthetic/default directory rows.",
299    },
300    OutputFieldDoc {
301        json_name: "date",
302        rust_field: "date",
303        value_shape: "string | null",
304        presence: "Emitted only on the file-info surface.",
305        meaning: "File date metadata on the opt-in file-info surface.",
306    },
307    OutputFieldDoc {
308        json_name: "sha1",
309        rust_field: "sha1",
310        value_shape: "string | null",
311        presence: "Emitted only on the file-info surface.",
312        meaning: "SHA-1 checksum on the opt-in file-info surface.",
313    },
314    OutputFieldDoc {
315        json_name: "md5",
316        rust_field: "md5",
317        value_shape: "string | null",
318        presence: "Emitted only on the file-info surface.",
319        meaning: "MD5 checksum on the opt-in file-info surface.",
320    },
321    OutputFieldDoc {
322        json_name: "sha256",
323        rust_field: "sha256",
324        value_shape: "string | null",
325        presence: "Emitted only on the file-info surface.",
326        meaning: "SHA-256 checksum on the opt-in file-info surface.",
327    },
328    OutputFieldDoc {
329        json_name: "sha1_git",
330        rust_field: "sha1_git",
331        value_shape: "string | null",
332        presence: "Emitted only on the file-info surface.",
333        meaning: "Git-style SHA-1 checksum on the opt-in file-info surface.",
334    },
335    OutputFieldDoc {
336        json_name: "mime_type",
337        rust_field: "mime_type",
338        value_shape: "string | null",
339        presence: "Emitted only on the file-info surface.",
340        meaning: "Detected MIME type on the opt-in file-info surface.",
341    },
342    OutputFieldDoc {
343        json_name: "file_type",
344        rust_field: "file_type_label",
345        value_shape: "string | null",
346        presence: "Emitted only on the file-info surface.",
347        meaning: "Additional file-type label on the opt-in file-info surface.",
348    },
349    OutputFieldDoc {
350        json_name: "programming_language",
351        rust_field: "programming_language",
352        value_shape: "string | null",
353        presence: "Emitted only on the file-info surface.",
354        meaning: "Language hint derived by file classification rather than package parsing.",
355    },
356    OutputFieldDoc {
357        json_name: "is_binary",
358        rust_field: "is_binary",
359        value_shape: "boolean | null",
360        presence: "Emitted only on the file-info surface.",
361        meaning: "Binary-file hint on the opt-in file-info surface.",
362    },
363    OutputFieldDoc {
364        json_name: "is_text",
365        rust_field: "is_text",
366        value_shape: "boolean | null",
367        presence: "Emitted only on the file-info surface.",
368        meaning: "Text-file hint on the opt-in file-info surface.",
369    },
370    OutputFieldDoc {
371        json_name: "is_archive",
372        rust_field: "is_archive",
373        value_shape: "boolean | null",
374        presence: "Emitted only on the file-info surface.",
375        meaning: "Archive-file hint on the opt-in file-info surface.",
376    },
377    OutputFieldDoc {
378        json_name: "is_media",
379        rust_field: "is_media",
380        value_shape: "boolean | null",
381        presence: "Emitted only on the file-info surface.",
382        meaning: "Media-file hint on the opt-in file-info surface.",
383    },
384    OutputFieldDoc {
385        json_name: "is_source",
386        rust_field: "is_source",
387        value_shape: "boolean | null",
388        presence: "Emitted only on the file-info surface.",
389        meaning: "Source-file hint on the opt-in file-info surface.",
390    },
391    OutputFieldDoc {
392        json_name: "is_script",
393        rust_field: "is_script",
394        value_shape: "boolean | null",
395        presence: "Emitted only on the file-info surface.",
396        meaning: "Script-file hint on the opt-in file-info surface.",
397    },
398    OutputFieldDoc {
399        json_name: "files_count",
400        rust_field: "files_count",
401        value_shape: "integer | null",
402        presence: "Emitted only on the file-info surface.",
403        meaning: "Nested file count on directory/info records when available.",
404    },
405    OutputFieldDoc {
406        json_name: "dirs_count",
407        rust_field: "dirs_count",
408        value_shape: "integer | null",
409        presence: "Emitted only on the file-info surface.",
410        meaning: "Nested directory count on directory/info records when available.",
411    },
412    OutputFieldDoc {
413        json_name: "size_count",
414        rust_field: "size_count",
415        value_shape: "integer | null",
416        presence: "Emitted only on the file-info surface.",
417        meaning: "Aggregated nested size count on directory/info records when available.",
418    },
419    OutputFieldDoc {
420        json_name: "package_data",
421        rust_field: "package_data",
422        value_shape: "array<object>",
423        presence: "Always emitted.",
424        meaning: "Raw parser-emitted package rows attached to this file record.",
425    },
426    OutputFieldDoc {
427        json_name: "detected_license_expression_spdx",
428        rust_field: "license_expression",
429        value_shape: "string | null",
430        presence: "Always emitted.",
431        meaning: "Primary SPDX-oriented file-level license expression after grouping detections and applying strict combination rules.",
432    },
433    OutputFieldDoc {
434        json_name: "license_detections",
435        rust_field: "license_detections",
436        value_shape: "array<object>",
437        presence: "Always emitted.",
438        meaning: "Grouped license detections attached to this file record.",
439    },
440    OutputFieldDoc {
441        json_name: "license_clues",
442        rust_field: "license_clues",
443        value_shape: "array<object>",
444        presence: "Emitted only when non-empty.",
445        meaning: "Low-confidence or clue-only matches that are surfaced separately from concrete detections.",
446    },
447    OutputFieldDoc {
448        json_name: "percentage_of_license_text",
449        rust_field: "percentage_of_license_text",
450        value_shape: "number | null",
451        presence: "Emitted only when a percentage was computed.",
452        meaning: "Approximate proportion of the file that participated in license text matches.",
453    },
454    OutputFieldDoc {
455        json_name: "copyrights",
456        rust_field: "copyrights",
457        value_shape: "array<object>",
458        presence: "Always emitted.",
459        meaning: "File-level copyright evidence records.",
460    },
461    OutputFieldDoc {
462        json_name: "holders",
463        rust_field: "holders",
464        value_shape: "array<object>",
465        presence: "Always emitted.",
466        meaning: "File-level holder evidence records.",
467    },
468    OutputFieldDoc {
469        json_name: "authors",
470        rust_field: "authors",
471        value_shape: "array<object>",
472        presence: "Always emitted.",
473        meaning: "File-level author evidence records.",
474    },
475    OutputFieldDoc {
476        json_name: "emails",
477        rust_field: "emails",
478        value_shape: "array<object>",
479        presence: "Emitted only when non-empty.",
480        meaning: "File-level extracted email records.",
481    },
482    OutputFieldDoc {
483        json_name: "urls",
484        rust_field: "urls",
485        value_shape: "array<object>",
486        presence: "Always emitted.",
487        meaning: "File-level extracted URL records.",
488    },
489    OutputFieldDoc {
490        json_name: "for_packages",
491        rust_field: "for_packages",
492        value_shape: "array<string>",
493        presence: "Always emitted.",
494        meaning: "Package UIDs that this file record is attached to after assembly or file-reference resolution.",
495    },
496    OutputFieldDoc {
497        json_name: "scan_errors",
498        rust_field: "scan_errors",
499        value_shape: "array<string>",
500        presence: "Always emitted.",
501        meaning: "Per-file problems that did not prevent the overall scan from completing.",
502    },
503    OutputFieldDoc {
504        json_name: "license_policy",
505        rust_field: "license_policy",
506        value_shape: "array<object> | null",
507        presence: "Emitted only when policy output is available.",
508        meaning: "Policy decoration entries attached to the file’s license findings when policy evaluation ran.",
509    },
510    OutputFieldDoc {
511        json_name: "is_generated",
512        rust_field: "is_generated",
513        value_shape: "boolean | null",
514        presence: "Emitted only when generated-code classification ran.",
515        meaning: "Generated-code signal on the info/classification surface.",
516    },
517    OutputFieldDoc {
518        json_name: "source_count",
519        rust_field: "source_count",
520        value_shape: "integer | null",
521        presence: "Emitted only when source counts are available.",
522        meaning: "Count of nested source files on directory/info records when available.",
523    },
524    OutputFieldDoc {
525        json_name: "is_legal",
526        rust_field: "is_legal",
527        value_shape: "boolean",
528        presence: "Emitted only when true.",
529        meaning: "Marks a file treated as legal-material evidence for key-file and summary logic.",
530    },
531    OutputFieldDoc {
532        json_name: "is_manifest",
533        rust_field: "is_manifest",
534        value_shape: "boolean",
535        presence: "Emitted only when true.",
536        meaning: "Marks a file treated as a manifest-like key file for package or summary logic.",
537    },
538    OutputFieldDoc {
539        json_name: "is_readme",
540        rust_field: "is_readme",
541        value_shape: "boolean",
542        presence: "Emitted only when true.",
543        meaning: "Marks a file treated as README-style descriptive project metadata.",
544    },
545    OutputFieldDoc {
546        json_name: "is_top_level",
547        rust_field: "is_top_level",
548        value_shape: "boolean",
549        presence: "Emitted only when true.",
550        meaning: "Marks a file treated as top-level for summary or package-root reasoning, even if filesystem depth differs.",
551    },
552    OutputFieldDoc {
553        json_name: "is_key_file",
554        rust_field: "is_key_file",
555        value_shape: "boolean",
556        presence: "Emitted only when true.",
557        meaning: "Marks a file that participates directly in summary and license clarity scoring.",
558    },
559    OutputFieldDoc {
560        json_name: "is_referenced",
561        rust_field: "is_referenced",
562        value_shape: "boolean",
563        presence: "Emitted only when true.",
564        meaning: "Marks a file whose content was followed as referenced evidence from another scanned file or package record.",
565    },
566    OutputFieldDoc {
567        json_name: "is_community",
568        rust_field: "is_community",
569        value_shape: "boolean",
570        presence: "Emitted only when true.",
571        meaning: "Marks a file treated as community-material evidence on the classification surface.",
572    },
573    OutputFieldDoc {
574        json_name: "facets",
575        rust_field: "facets",
576        value_shape: "array<string>",
577        presence: "Emitted only when non-empty.",
578        meaning: "Facet labels attached by user-defined facet rules for tally grouping.",
579    },
580    OutputFieldDoc {
581        json_name: "tallies",
582        rust_field: "tallies",
583        value_shape: "object | null",
584        presence: "Emitted only when file-level tallies were requested.",
585        meaning: "Per-file or per-directory tally block emitted by detailed tally workflows.",
586    },
587];
588
589const PACKAGE_FIELDS: &[OutputFieldDoc] = &[
590    OutputFieldDoc {
591        json_name: "type",
592        rust_field: "package_type",
593        value_shape: "string | null",
594        presence: "Always emitted.",
595        meaning: "Package ecosystem/type identifier on the public ScanCode-compatible surface.",
596    },
597    OutputFieldDoc {
598        json_name: "namespace",
599        rust_field: "namespace",
600        value_shape: "string | null",
601        presence: "Always emitted.",
602        meaning: "Package namespace on the public package surface.",
603    },
604    OutputFieldDoc {
605        json_name: "name",
606        rust_field: "name",
607        value_shape: "string | null",
608        presence: "Always emitted.",
609        meaning: "Package name on the public package surface.",
610    },
611    OutputFieldDoc {
612        json_name: "version",
613        rust_field: "version",
614        value_shape: "string | null",
615        presence: "Always emitted.",
616        meaning: "Package version on the public package surface.",
617    },
618    OutputFieldDoc {
619        json_name: "qualifiers",
620        rust_field: "qualifiers",
621        value_shape: "object",
622        presence: "Always emitted.",
623        meaning: "PURL-style qualifier key/value pairs. Empty object when qualifiers are absent.",
624    },
625    OutputFieldDoc {
626        json_name: "subpath",
627        rust_field: "subpath",
628        value_shape: "string | null",
629        presence: "Always emitted.",
630        meaning: "Package subpath on the public package surface.",
631    },
632    OutputFieldDoc {
633        json_name: "primary_language",
634        rust_field: "primary_language",
635        value_shape: "string | null",
636        presence: "Always emitted.",
637        meaning: "Primary language associated with the package.",
638    },
639    OutputFieldDoc {
640        json_name: "description",
641        rust_field: "description",
642        value_shape: "string | null",
643        presence: "Always emitted.",
644        meaning: "Package description.",
645    },
646    OutputFieldDoc {
647        json_name: "release_date",
648        rust_field: "release_date",
649        value_shape: "string | null",
650        presence: "Always emitted.",
651        meaning: "Package release date.",
652    },
653    OutputFieldDoc {
654        json_name: "parties",
655        rust_field: "parties",
656        value_shape: "array<object>",
657        presence: "Always emitted.",
658        meaning: "Party records attached to the package.",
659    },
660    OutputFieldDoc {
661        json_name: "keywords",
662        rust_field: "keywords",
663        value_shape: "array<string>",
664        presence: "Always emitted.",
665        meaning: "Keywords attached to the package.",
666    },
667    OutputFieldDoc {
668        json_name: "homepage_url",
669        rust_field: "homepage_url",
670        value_shape: "string | null",
671        presence: "Always emitted.",
672        meaning: "Package homepage URL.",
673    },
674    OutputFieldDoc {
675        json_name: "download_url",
676        rust_field: "download_url",
677        value_shape: "string | null",
678        presence: "Always emitted.",
679        meaning: "Package download URL.",
680    },
681    OutputFieldDoc {
682        json_name: "size",
683        rust_field: "size",
684        value_shape: "integer | null",
685        presence: "Always emitted.",
686        meaning: "Package size when known.",
687    },
688    OutputFieldDoc {
689        json_name: "sha1",
690        rust_field: "sha1",
691        value_shape: "string | null",
692        presence: "Always emitted.",
693        meaning: "Package SHA-1 checksum when known.",
694    },
695    OutputFieldDoc {
696        json_name: "md5",
697        rust_field: "md5",
698        value_shape: "string | null",
699        presence: "Always emitted.",
700        meaning: "Package MD5 checksum when known.",
701    },
702    OutputFieldDoc {
703        json_name: "sha256",
704        rust_field: "sha256",
705        value_shape: "string | null",
706        presence: "Always emitted.",
707        meaning: "Package SHA-256 checksum when known.",
708    },
709    OutputFieldDoc {
710        json_name: "sha512",
711        rust_field: "sha512",
712        value_shape: "string | null",
713        presence: "Always emitted.",
714        meaning: "Package SHA-512 checksum when known.",
715    },
716    OutputFieldDoc {
717        json_name: "bug_tracking_url",
718        rust_field: "bug_tracking_url",
719        value_shape: "string | null",
720        presence: "Always emitted.",
721        meaning: "Package bug-tracker URL.",
722    },
723    OutputFieldDoc {
724        json_name: "code_view_url",
725        rust_field: "code_view_url",
726        value_shape: "string | null",
727        presence: "Always emitted.",
728        meaning: "Package code-view URL.",
729    },
730    OutputFieldDoc {
731        json_name: "vcs_url",
732        rust_field: "vcs_url",
733        value_shape: "string | null",
734        presence: "Always emitted.",
735        meaning: "Package VCS URL.",
736    },
737    OutputFieldDoc {
738        json_name: "copyright",
739        rust_field: "copyright",
740        value_shape: "string | null",
741        presence: "Always emitted.",
742        meaning: "Package copyright string.",
743    },
744    OutputFieldDoc {
745        json_name: "holder",
746        rust_field: "holder",
747        value_shape: "string | null",
748        presence: "Always emitted.",
749        meaning: "Package holder string.",
750    },
751    OutputFieldDoc {
752        json_name: "declared_license_expression",
753        rust_field: "declared_license_expression",
754        value_shape: "string | null",
755        presence: "Always emitted.",
756        meaning: "Primary declared license expression on the package record.",
757    },
758    OutputFieldDoc {
759        json_name: "declared_license_expression_spdx",
760        rust_field: "declared_license_expression_spdx",
761        value_shape: "string | null",
762        presence: "Always emitted.",
763        meaning: "SPDX-form primary declared license expression on the package record.",
764    },
765    OutputFieldDoc {
766        json_name: "license_detections",
767        rust_field: "license_detections",
768        value_shape: "array<object>",
769        presence: "Always emitted.",
770        meaning: "Structured declared or extracted license detections attached to the package record.",
771    },
772    OutputFieldDoc {
773        json_name: "other_license_expression",
774        rust_field: "other_license_expression",
775        value_shape: "string | null",
776        presence: "Always emitted.",
777        meaning: "Non-primary declared license text normalized into an auxiliary expression lane.",
778    },
779    OutputFieldDoc {
780        json_name: "other_license_expression_spdx",
781        rust_field: "other_license_expression_spdx",
782        value_shape: "string | null",
783        presence: "Always emitted.",
784        meaning: "SPDX-form auxiliary non-primary declared license expression on the package record.",
785    },
786    OutputFieldDoc {
787        json_name: "other_license_detections",
788        rust_field: "other_license_detections",
789        value_shape: "array<object>",
790        presence: "Always emitted.",
791        meaning: "Detections associated with the auxiliary or non-primary license lane.",
792    },
793    OutputFieldDoc {
794        json_name: "extracted_license_statement",
795        rust_field: "extracted_license_statement",
796        value_shape: "string | null",
797        presence: "Always emitted.",
798        meaning: "Raw extracted license statement on the package record.",
799    },
800    OutputFieldDoc {
801        json_name: "notice_text",
802        rust_field: "notice_text",
803        value_shape: "string | null",
804        presence: "Always emitted.",
805        meaning: "Package notice text.",
806    },
807    OutputFieldDoc {
808        json_name: "source_packages",
809        rust_field: "source_packages",
810        value_shape: "array<string>",
811        presence: "Always emitted.",
812        meaning: "Referenced source-package package URLs or identifiers associated with this package.",
813    },
814    OutputFieldDoc {
815        json_name: "is_private",
816        rust_field: "is_private",
817        value_shape: "boolean",
818        presence: "Always emitted.",
819        meaning: "Package-level private/public signal when the parser or datasource can state it confidently.",
820    },
821    OutputFieldDoc {
822        json_name: "is_virtual",
823        rust_field: "is_virtual",
824        value_shape: "boolean",
825        presence: "Always emitted.",
826        meaning: "Marks package records that represent virtual or synthetic package identities rather than concrete deliverables.",
827    },
828    OutputFieldDoc {
829        json_name: "extra_data",
830        rust_field: "extra_data",
831        value_shape: "object",
832        presence: "Always emitted.",
833        meaning: "Datasource-specific structured metadata preserved without promoting it into the core package contract. Empty object when extra data is absent.",
834    },
835    OutputFieldDoc {
836        json_name: "repository_homepage_url",
837        rust_field: "repository_homepage_url",
838        value_shape: "string | null",
839        presence: "Always emitted.",
840        meaning: "Repository homepage URL for the package.",
841    },
842    OutputFieldDoc {
843        json_name: "repository_download_url",
844        rust_field: "repository_download_url",
845        value_shape: "string | null",
846        presence: "Always emitted.",
847        meaning: "Repository download URL for the package.",
848    },
849    OutputFieldDoc {
850        json_name: "api_data_url",
851        rust_field: "api_data_url",
852        value_shape: "string | null",
853        presence: "Always emitted.",
854        meaning: "API data URL for the package.",
855    },
856    OutputFieldDoc {
857        json_name: "purl",
858        rust_field: "purl",
859        value_shape: "string | null",
860        presence: "Always emitted.",
861        meaning: "Package URL for the package record.",
862    },
863    OutputFieldDoc {
864        json_name: "package_uid",
865        rust_field: "package_uid",
866        value_shape: "string",
867        presence: "Always emitted.",
868        meaning: "Stable package identifier used internally and on output links such as `for_packages`.",
869    },
870    OutputFieldDoc {
871        json_name: "datafile_paths",
872        rust_field: "datafile_paths",
873        value_shape: "array<string>",
874        presence: "Always emitted.",
875        meaning: "Manifest or metadata file paths that contributed to this assembled package record.",
876    },
877    OutputFieldDoc {
878        json_name: "datasource_ids",
879        rust_field: "datasource_ids",
880        value_shape: "array<string>",
881        presence: "Always emitted.",
882        meaning: "Datasource identifiers that explain which parser/input surfaces contributed to this package record.",
883    },
884];
885
886const PACKAGE_DATA_FIELDS: &[OutputFieldDoc] = &[
887    OutputFieldDoc {
888        json_name: "type",
889        rust_field: "package_type",
890        value_shape: "string | null",
891        presence: "Always emitted.",
892        meaning: "Package ecosystem/type identifier on a file-local package_data row.",
893    },
894    OutputFieldDoc {
895        json_name: "namespace",
896        rust_field: "namespace",
897        value_shape: "string | null",
898        presence: "Always emitted.",
899        meaning: "Package namespace on the file-local package_data row.",
900    },
901    OutputFieldDoc {
902        json_name: "name",
903        rust_field: "name",
904        value_shape: "string | null",
905        presence: "Always emitted.",
906        meaning: "Package name on the file-local package_data row.",
907    },
908    OutputFieldDoc {
909        json_name: "version",
910        rust_field: "version",
911        value_shape: "string | null",
912        presence: "Always emitted.",
913        meaning: "Package version on the file-local package_data row.",
914    },
915    OutputFieldDoc {
916        json_name: "qualifiers",
917        rust_field: "qualifiers",
918        value_shape: "object",
919        presence: "Always emitted.",
920        meaning: "PURL-style qualifier key/value pairs on a file-local package_data row.",
921    },
922    OutputFieldDoc {
923        json_name: "subpath",
924        rust_field: "subpath",
925        value_shape: "string | null",
926        presence: "Always emitted.",
927        meaning: "Package subpath on the file-local package_data row.",
928    },
929    OutputFieldDoc {
930        json_name: "primary_language",
931        rust_field: "primary_language",
932        value_shape: "string | null",
933        presence: "Always emitted.",
934        meaning: "Primary language associated with the file-local package_data row.",
935    },
936    OutputFieldDoc {
937        json_name: "description",
938        rust_field: "description",
939        value_shape: "string | null",
940        presence: "Always emitted.",
941        meaning: "Package description on the file-local package_data row.",
942    },
943    OutputFieldDoc {
944        json_name: "release_date",
945        rust_field: "release_date",
946        value_shape: "string | null",
947        presence: "Always emitted.",
948        meaning: "Release date on the file-local package_data row.",
949    },
950    OutputFieldDoc {
951        json_name: "parties",
952        rust_field: "parties",
953        value_shape: "array<object>",
954        presence: "Always emitted.",
955        meaning: "Party records attached to the file-local package_data row.",
956    },
957    OutputFieldDoc {
958        json_name: "keywords",
959        rust_field: "keywords",
960        value_shape: "array<string>",
961        presence: "Always emitted.",
962        meaning: "Keywords attached to the file-local package_data row.",
963    },
964    OutputFieldDoc {
965        json_name: "homepage_url",
966        rust_field: "homepage_url",
967        value_shape: "string | null",
968        presence: "Always emitted.",
969        meaning: "Homepage URL on the file-local package_data row.",
970    },
971    OutputFieldDoc {
972        json_name: "download_url",
973        rust_field: "download_url",
974        value_shape: "string | null",
975        presence: "Always emitted.",
976        meaning: "Download URL on the file-local package_data row.",
977    },
978    OutputFieldDoc {
979        json_name: "size",
980        rust_field: "size",
981        value_shape: "integer | null",
982        presence: "Always emitted.",
983        meaning: "Package size on the file-local package_data row when known.",
984    },
985    OutputFieldDoc {
986        json_name: "sha1",
987        rust_field: "sha1",
988        value_shape: "string | null",
989        presence: "Always emitted.",
990        meaning: "SHA-1 checksum on the file-local package_data row when known.",
991    },
992    OutputFieldDoc {
993        json_name: "md5",
994        rust_field: "md5",
995        value_shape: "string | null",
996        presence: "Always emitted.",
997        meaning: "MD5 checksum on the file-local package_data row when known.",
998    },
999    OutputFieldDoc {
1000        json_name: "sha256",
1001        rust_field: "sha256",
1002        value_shape: "string | null",
1003        presence: "Always emitted.",
1004        meaning: "SHA-256 checksum on the file-local package_data row when known.",
1005    },
1006    OutputFieldDoc {
1007        json_name: "sha512",
1008        rust_field: "sha512",
1009        value_shape: "string | null",
1010        presence: "Always emitted.",
1011        meaning: "SHA-512 checksum on the file-local package_data row when known.",
1012    },
1013    OutputFieldDoc {
1014        json_name: "bug_tracking_url",
1015        rust_field: "bug_tracking_url",
1016        value_shape: "string | null",
1017        presence: "Always emitted.",
1018        meaning: "Bug-tracker URL on the file-local package_data row.",
1019    },
1020    OutputFieldDoc {
1021        json_name: "code_view_url",
1022        rust_field: "code_view_url",
1023        value_shape: "string | null",
1024        presence: "Always emitted.",
1025        meaning: "Code-view URL on the file-local package_data row.",
1026    },
1027    OutputFieldDoc {
1028        json_name: "vcs_url",
1029        rust_field: "vcs_url",
1030        value_shape: "string | null",
1031        presence: "Always emitted.",
1032        meaning: "VCS URL on the file-local package_data row.",
1033    },
1034    OutputFieldDoc {
1035        json_name: "copyright",
1036        rust_field: "copyright",
1037        value_shape: "string | null",
1038        presence: "Always emitted.",
1039        meaning: "Copyright string on the file-local package_data row.",
1040    },
1041    OutputFieldDoc {
1042        json_name: "holder",
1043        rust_field: "holder",
1044        value_shape: "string | null",
1045        presence: "Always emitted.",
1046        meaning: "Holder string on the file-local package_data row.",
1047    },
1048    OutputFieldDoc {
1049        json_name: "declared_license_expression",
1050        rust_field: "declared_license_expression",
1051        value_shape: "string | null",
1052        presence: "Always emitted.",
1053        meaning: "Primary declared license expression on the file-local package_data row.",
1054    },
1055    OutputFieldDoc {
1056        json_name: "declared_license_expression_spdx",
1057        rust_field: "declared_license_expression_spdx",
1058        value_shape: "string | null",
1059        presence: "Always emitted.",
1060        meaning: "SPDX-form primary declared license expression on the file-local package_data row.",
1061    },
1062    OutputFieldDoc {
1063        json_name: "license_detections",
1064        rust_field: "license_detections",
1065        value_shape: "array<object>",
1066        presence: "Always emitted.",
1067        meaning: "Structured license detections attached to the raw parser-emitted package_data row.",
1068    },
1069    OutputFieldDoc {
1070        json_name: "other_license_expression",
1071        rust_field: "other_license_expression",
1072        value_shape: "string | null",
1073        presence: "Always emitted.",
1074        meaning: "Auxiliary non-primary license expression lane for the package_data row.",
1075    },
1076    OutputFieldDoc {
1077        json_name: "other_license_expression_spdx",
1078        rust_field: "other_license_expression_spdx",
1079        value_shape: "string | null",
1080        presence: "Always emitted.",
1081        meaning: "SPDX-form auxiliary non-primary license expression lane for the package_data row.",
1082    },
1083    OutputFieldDoc {
1084        json_name: "other_license_detections",
1085        rust_field: "other_license_detections",
1086        value_shape: "array<object>",
1087        presence: "Always emitted.",
1088        meaning: "Detections associated with the auxiliary or non-primary license lane.",
1089    },
1090    OutputFieldDoc {
1091        json_name: "extracted_license_statement",
1092        rust_field: "extracted_license_statement",
1093        value_shape: "string | null",
1094        presence: "Always emitted.",
1095        meaning: "Raw extracted license statement on the package_data row.",
1096    },
1097    OutputFieldDoc {
1098        json_name: "notice_text",
1099        rust_field: "notice_text",
1100        value_shape: "string | null",
1101        presence: "Always emitted.",
1102        meaning: "Notice text on the package_data row.",
1103    },
1104    OutputFieldDoc {
1105        json_name: "source_packages",
1106        rust_field: "source_packages",
1107        value_shape: "array<string>",
1108        presence: "Always emitted.",
1109        meaning: "Referenced source-package identifiers preserved on the raw package_data row.",
1110    },
1111    OutputFieldDoc {
1112        json_name: "file_references",
1113        rust_field: "file_references",
1114        value_shape: "array<object>",
1115        presence: "Always emitted.",
1116        meaning: "File-reference hints emitted by parsers for later resolution or ownership assignment.",
1117    },
1118    OutputFieldDoc {
1119        json_name: "is_private",
1120        rust_field: "is_private",
1121        value_shape: "boolean",
1122        presence: "Always emitted.",
1123        meaning: "Private/public package signal on the raw parser-emitted row.",
1124    },
1125    OutputFieldDoc {
1126        json_name: "is_virtual",
1127        rust_field: "is_virtual",
1128        value_shape: "boolean",
1129        presence: "Always emitted.",
1130        meaning: "Virtual/synthetic package signal on the raw parser-emitted row.",
1131    },
1132    OutputFieldDoc {
1133        json_name: "extra_data",
1134        rust_field: "extra_data",
1135        value_shape: "object",
1136        presence: "Always emitted.",
1137        meaning: "Datasource-specific structured metadata preserved without promotion into core fields.",
1138    },
1139    OutputFieldDoc {
1140        json_name: "dependencies",
1141        rust_field: "dependencies",
1142        value_shape: "array<object>",
1143        presence: "Always emitted.",
1144        meaning: "Raw dependency rows emitted directly by the parser before top-level assembly.",
1145    },
1146    OutputFieldDoc {
1147        json_name: "repository_homepage_url",
1148        rust_field: "repository_homepage_url",
1149        value_shape: "string | null",
1150        presence: "Always emitted.",
1151        meaning: "Repository homepage URL on the file-local package_data row.",
1152    },
1153    OutputFieldDoc {
1154        json_name: "repository_download_url",
1155        rust_field: "repository_download_url",
1156        value_shape: "string | null",
1157        presence: "Always emitted.",
1158        meaning: "Repository download URL on the file-local package_data row.",
1159    },
1160    OutputFieldDoc {
1161        json_name: "api_data_url",
1162        rust_field: "api_data_url",
1163        value_shape: "string | null",
1164        presence: "Always emitted.",
1165        meaning: "API data URL on the file-local package_data row.",
1166    },
1167    OutputFieldDoc {
1168        json_name: "datasource_id",
1169        rust_field: "datasource_id",
1170        value_shape: "string | null",
1171        presence: "Always emitted.",
1172        meaning: "Single datasource identifier for the parser surface that produced this package_data row.",
1173    },
1174    OutputFieldDoc {
1175        json_name: "purl",
1176        rust_field: "purl",
1177        value_shape: "string | null",
1178        presence: "Always emitted.",
1179        meaning: "Package URL on the file-local package_data row.",
1180    },
1181];
1182
1183const DEPENDENCY_FIELDS: &[OutputFieldDoc] = &[
1184    OutputFieldDoc {
1185        json_name: "purl",
1186        rust_field: "purl",
1187        value_shape: "string | null",
1188        presence: "Always emitted.",
1189        meaning: "Package URL for the dependency row.",
1190    },
1191    OutputFieldDoc {
1192        json_name: "extracted_requirement",
1193        rust_field: "extracted_requirement",
1194        value_shape: "string | null",
1195        presence: "Always emitted.",
1196        meaning: "Raw requirement/version constraint text extracted from the manifest or lockfile.",
1197    },
1198    OutputFieldDoc {
1199        json_name: "scope",
1200        rust_field: "scope",
1201        value_shape: "string | null",
1202        presence: "Always emitted.",
1203        meaning: "Datasource-specific dependency scope such as runtime/dev/test/build.",
1204    },
1205    OutputFieldDoc {
1206        json_name: "is_runtime",
1207        rust_field: "is_runtime",
1208        value_shape: "boolean | null",
1209        presence: "Always emitted.",
1210        meaning: "Normalized runtime intent signal when it can be derived honestly.",
1211    },
1212    OutputFieldDoc {
1213        json_name: "is_optional",
1214        rust_field: "is_optional",
1215        value_shape: "boolean | null",
1216        presence: "Always emitted.",
1217        meaning: "Normalized optional-dependency signal when it can be derived honestly.",
1218    },
1219    OutputFieldDoc {
1220        json_name: "is_pinned",
1221        rust_field: "is_pinned",
1222        value_shape: "boolean | null",
1223        presence: "Always emitted.",
1224        meaning: "Normalized version-pinning signal when it can be derived honestly.",
1225    },
1226    OutputFieldDoc {
1227        json_name: "is_direct",
1228        rust_field: "is_direct",
1229        value_shape: "boolean | null",
1230        presence: "Always emitted.",
1231        meaning: "Normalized direct-vs-transitive signal when it can be derived honestly.",
1232    },
1233    OutputFieldDoc {
1234        json_name: "resolved_package",
1235        rust_field: "resolved_package",
1236        value_shape: "object | null",
1237        presence: "Always emitted.",
1238        meaning: "Resolved package identity/details nested directly under the dependency row.",
1239    },
1240    OutputFieldDoc {
1241        json_name: "extra_data",
1242        rust_field: "extra_data",
1243        value_shape: "object",
1244        presence: "Always emitted.",
1245        meaning: "Datasource-specific dependency metadata preserved without promotion into core fields.",
1246    },
1247];
1248
1249const TOP_LEVEL_DEPENDENCY_FIELDS: &[OutputFieldDoc] = &[
1250    OutputFieldDoc {
1251        json_name: "purl",
1252        rust_field: "purl",
1253        value_shape: "string | null",
1254        presence: "Always emitted.",
1255        meaning: "Package URL for the top-level dependency row.",
1256    },
1257    OutputFieldDoc {
1258        json_name: "extracted_requirement",
1259        rust_field: "extracted_requirement",
1260        value_shape: "string | null",
1261        presence: "Always emitted.",
1262        meaning: "Raw requirement/version constraint text for the top-level dependency row.",
1263    },
1264    OutputFieldDoc {
1265        json_name: "scope",
1266        rust_field: "scope",
1267        value_shape: "string | null",
1268        presence: "Always emitted.",
1269        meaning: "Datasource-specific dependency scope such as runtime/dev/test/build.",
1270    },
1271    OutputFieldDoc {
1272        json_name: "is_runtime",
1273        rust_field: "is_runtime",
1274        value_shape: "boolean | null",
1275        presence: "Always emitted.",
1276        meaning: "Normalized runtime intent signal when it can be derived honestly.",
1277    },
1278    OutputFieldDoc {
1279        json_name: "is_optional",
1280        rust_field: "is_optional",
1281        value_shape: "boolean | null",
1282        presence: "Always emitted.",
1283        meaning: "Normalized optional-dependency signal when it can be derived honestly.",
1284    },
1285    OutputFieldDoc {
1286        json_name: "is_pinned",
1287        rust_field: "is_pinned",
1288        value_shape: "boolean | null",
1289        presence: "Always emitted.",
1290        meaning: "Normalized version-pinning signal when it can be derived honestly.",
1291    },
1292    OutputFieldDoc {
1293        json_name: "is_direct",
1294        rust_field: "is_direct",
1295        value_shape: "boolean | null",
1296        presence: "Always emitted.",
1297        meaning: "Normalized direct-vs-transitive signal when it can be derived honestly.",
1298    },
1299    OutputFieldDoc {
1300        json_name: "resolved_package",
1301        rust_field: "resolved_package",
1302        value_shape: "object | null",
1303        presence: "Always emitted.",
1304        meaning: "Resolved package payload nested under the top-level dependency row.",
1305    },
1306    OutputFieldDoc {
1307        json_name: "extra_data",
1308        rust_field: "extra_data",
1309        value_shape: "object",
1310        presence: "Always emitted.",
1311        meaning: "Datasource-specific structured metadata preserved on the top-level dependency row.",
1312    },
1313    OutputFieldDoc {
1314        json_name: "dependency_uid",
1315        rust_field: "dependency_uid",
1316        value_shape: "string",
1317        presence: "Always emitted.",
1318        meaning: "Stable identifier for the top-level dependency row on the public contract.",
1319    },
1320    OutputFieldDoc {
1321        json_name: "for_package_uid",
1322        rust_field: "for_package_uid",
1323        value_shape: "string | null",
1324        presence: "Always emitted.",
1325        meaning: "Package UID that owns this hoisted dependency row after assembly.",
1326    },
1327    OutputFieldDoc {
1328        json_name: "datafile_path",
1329        rust_field: "datafile_path",
1330        value_shape: "string",
1331        presence: "Always emitted.",
1332        meaning: "Manifest or metadata file path that contributed this top-level dependency row.",
1333    },
1334    OutputFieldDoc {
1335        json_name: "datasource_id",
1336        rust_field: "datasource_id",
1337        value_shape: "string",
1338        presence: "Always emitted.",
1339        meaning: "Datasource identifier for the parser/input surface that contributed this row.",
1340    },
1341    OutputFieldDoc {
1342        json_name: "namespace",
1343        rust_field: "namespace",
1344        value_shape: "string | null",
1345        presence: "Always emitted.",
1346        meaning: "Owning namespace lane preserved on the hoisted dependency row for output compatibility.",
1347    },
1348];
1349
1350const TOP_LEVEL_LICENSE_DETECTION_FIELDS: &[OutputFieldDoc] = &[
1351    OutputFieldDoc {
1352        json_name: "identifier",
1353        rust_field: "identifier",
1354        value_shape: "string",
1355        presence: "Always emitted.",
1356        meaning: "Stable grouped-detection identifier for this top-level license detection block.",
1357    },
1358    OutputFieldDoc {
1359        json_name: "license_expression",
1360        rust_field: "license_expression",
1361        value_shape: "string",
1362        presence: "Always emitted.",
1363        meaning: "Grouped license expression for the top-level detection block.",
1364    },
1365    OutputFieldDoc {
1366        json_name: "license_expression_spdx",
1367        rust_field: "license_expression_spdx",
1368        value_shape: "string",
1369        presence: "Always emitted.",
1370        meaning: "SPDX-form grouped license expression for the top-level detection block.",
1371    },
1372    OutputFieldDoc {
1373        json_name: "detection_count",
1374        rust_field: "detection_count",
1375        value_shape: "integer",
1376        presence: "Always emitted.",
1377        meaning: "Number of file-level detections that contributed to this grouped top-level block.",
1378    },
1379    OutputFieldDoc {
1380        json_name: "detection_log",
1381        rust_field: "detection_log",
1382        value_shape: "array<string>",
1383        presence: "Emitted only when non-empty.",
1384        meaning: "Grouping-time notes that explain why this top-level detection looks the way it does.",
1385    },
1386    OutputFieldDoc {
1387        json_name: "reference_matches",
1388        rust_field: "reference_matches",
1389        value_shape: "array<object>",
1390        presence: "Always emitted.",
1391        meaning: "Representative match/reference records retained on the top-level grouped detection block.",
1392    },
1393];
1394
1395const TALLIES_FIELDS: &[OutputFieldDoc] = &[
1396    OutputFieldDoc {
1397        json_name: "detected_license_expression",
1398        rust_field: "detected_license_expression",
1399        value_shape: "array<object>",
1400        presence: "Emitted only when non-empty.",
1401        meaning: "Tally entries for file-level detected license expressions.",
1402    },
1403    OutputFieldDoc {
1404        json_name: "copyrights",
1405        rust_field: "copyrights",
1406        value_shape: "array<object>",
1407        presence: "Emitted only when non-empty.",
1408        meaning: "Tally entries for copyright strings.",
1409    },
1410    OutputFieldDoc {
1411        json_name: "holders",
1412        rust_field: "holders",
1413        value_shape: "array<object>",
1414        presence: "Emitted only when non-empty.",
1415        meaning: "Tally entries for copyright holders.",
1416    },
1417    OutputFieldDoc {
1418        json_name: "authors",
1419        rust_field: "authors",
1420        value_shape: "array<object>",
1421        presence: "Emitted only when non-empty.",
1422        meaning: "Tally entries for author strings.",
1423    },
1424    OutputFieldDoc {
1425        json_name: "programming_language",
1426        rust_field: "programming_language",
1427        value_shape: "array<object>",
1428        presence: "Emitted only when non-empty.",
1429        meaning: "Tally entries for detected programming-language hints.",
1430    },
1431];
1432
1433const FACET_TALLIES_FIELDS: &[OutputFieldDoc] = &[
1434    OutputFieldDoc {
1435        json_name: "facet",
1436        rust_field: "facet",
1437        value_shape: "string",
1438        presence: "Always emitted.",
1439        meaning: "Facet label for this grouped tally block.",
1440    },
1441    OutputFieldDoc {
1442        json_name: "tallies",
1443        rust_field: "tallies",
1444        value_shape: "object",
1445        presence: "Always emitted.",
1446        meaning: "Tally payload for this single facet.",
1447    },
1448];
1449
1450const TALLY_ENTRY_FIELDS: &[OutputFieldDoc] = &[
1451    OutputFieldDoc {
1452        json_name: "value",
1453        rust_field: "value",
1454        value_shape: "string | null",
1455        presence: "Always emitted.",
1456        meaning: "Bucket value represented by the tally row.",
1457    },
1458    OutputFieldDoc {
1459        json_name: "count",
1460        rust_field: "count",
1461        value_shape: "integer",
1462        presence: "Always emitted.",
1463        meaning: "Number of occurrences counted into this tally bucket.",
1464    },
1465];
1466
1467const LICENSE_CLARITY_SCORE_FIELDS: &[OutputFieldDoc] = &[
1468    OutputFieldDoc {
1469        json_name: "score",
1470        rust_field: "score",
1471        value_shape: "integer",
1472        presence: "Always emitted.",
1473        meaning: "Overall clarity score for the summary-level licensing evidence.",
1474    },
1475    OutputFieldDoc {
1476        json_name: "declared_license",
1477        rust_field: "declared_license",
1478        value_shape: "boolean",
1479        presence: "Always emitted.",
1480        meaning: "Whether clear declared-license evidence was found.",
1481    },
1482    OutputFieldDoc {
1483        json_name: "identification_precision",
1484        rust_field: "identification_precision",
1485        value_shape: "boolean",
1486        presence: "Always emitted.",
1487        meaning: "Whether the detected licensing evidence is precise rather than vague or generic.",
1488    },
1489    OutputFieldDoc {
1490        json_name: "has_license_text",
1491        rust_field: "has_license_text",
1492        value_shape: "boolean",
1493        presence: "Always emitted.",
1494        meaning: "Whether substantive license-text evidence was found.",
1495    },
1496    OutputFieldDoc {
1497        json_name: "declared_copyrights",
1498        rust_field: "declared_copyrights",
1499        value_shape: "boolean",
1500        presence: "Always emitted.",
1501        meaning: "Whether declared copyright evidence was found in the key-file set.",
1502    },
1503    OutputFieldDoc {
1504        json_name: "conflicting_license_categories",
1505        rust_field: "conflicting_license_categories",
1506        value_shape: "boolean",
1507        presence: "Always emitted.",
1508        meaning: "Whether the evidence contains conflicting license-category signals.",
1509    },
1510    OutputFieldDoc {
1511        json_name: "ambiguous_compound_licensing",
1512        rust_field: "ambiguous_compound_licensing",
1513        value_shape: "boolean",
1514        presence: "Always emitted.",
1515        meaning: "Whether the evidence suggests a compound license situation that remains ambiguous.",
1516    },
1517];
1518
1519const SYSTEM_ENVIRONMENT_FIELDS: &[OutputFieldDoc] = &[
1520    OutputFieldDoc {
1521        json_name: "operating_system",
1522        rust_field: "operating_system",
1523        value_shape: "string",
1524        presence: "Always emitted.",
1525        meaning: "Operating-system name recorded for the scan environment.",
1526    },
1527    OutputFieldDoc {
1528        json_name: "cpu_architecture",
1529        rust_field: "cpu_architecture",
1530        value_shape: "string",
1531        presence: "Always emitted.",
1532        meaning: "CPU architecture recorded for the scan environment.",
1533    },
1534    OutputFieldDoc {
1535        json_name: "platform",
1536        rust_field: "platform",
1537        value_shape: "string",
1538        presence: "Always emitted.",
1539        meaning: "Platform family recorded for the scan environment.",
1540    },
1541    OutputFieldDoc {
1542        json_name: "platform_version",
1543        rust_field: "platform_version",
1544        value_shape: "string",
1545        presence: "Always emitted.",
1546        meaning: "Platform version recorded for the scan environment.",
1547    },
1548    OutputFieldDoc {
1549        json_name: "rust_version",
1550        rust_field: "rust_version",
1551        value_shape: "string",
1552        presence: "Always emitted.",
1553        meaning: "Rust toolchain version used by the scanner binary.",
1554    },
1555];
1556
1557const LICENSE_INDEX_PROVENANCE_FIELDS: &[OutputFieldDoc] = &[
1558    OutputFieldDoc {
1559        json_name: "source",
1560        rust_field: "source",
1561        value_shape: "string",
1562        presence: "Always emitted.",
1563        meaning: "Source lane for the effective license index, such as embedded or custom dataset.",
1564    },
1565    OutputFieldDoc {
1566        json_name: "dataset_fingerprint",
1567        rust_field: "dataset_fingerprint",
1568        value_shape: "string",
1569        presence: "Always emitted.",
1570        meaning: "Stable fingerprint for the effective license dataset contents.",
1571    },
1572    OutputFieldDoc {
1573        json_name: "ignored_rules",
1574        rust_field: "ignored_rules",
1575        value_shape: "array<string>",
1576        presence: "Emitted only when non-empty.",
1577        meaning: "Rule identifiers excluded while building the effective index.",
1578    },
1579    OutputFieldDoc {
1580        json_name: "ignored_licenses",
1581        rust_field: "ignored_licenses",
1582        value_shape: "array<string>",
1583        presence: "Emitted only when non-empty.",
1584        meaning: "License keys excluded while building the effective index.",
1585    },
1586    OutputFieldDoc {
1587        json_name: "ignored_rules_due_to_licenses",
1588        rust_field: "ignored_rules_due_to_licenses",
1589        value_shape: "array<string>",
1590        presence: "Emitted only when non-empty.",
1591        meaning: "Rules excluded indirectly because their owning licenses were excluded.",
1592    },
1593    OutputFieldDoc {
1594        json_name: "added_rules",
1595        rust_field: "added_rules",
1596        value_shape: "array<string>",
1597        presence: "Emitted only when non-empty.",
1598        meaning: "Rule identifiers added by local overlays or custom dataset input.",
1599    },
1600    OutputFieldDoc {
1601        json_name: "replaced_rules",
1602        rust_field: "replaced_rules",
1603        value_shape: "array<string>",
1604        presence: "Emitted only when non-empty.",
1605        meaning: "Rule identifiers replaced by local overlays or custom dataset input.",
1606    },
1607    OutputFieldDoc {
1608        json_name: "added_licenses",
1609        rust_field: "added_licenses",
1610        value_shape: "array<string>",
1611        presence: "Emitted only when non-empty.",
1612        meaning: "License keys added by local overlays or custom dataset input.",
1613    },
1614    OutputFieldDoc {
1615        json_name: "replaced_licenses",
1616        rust_field: "replaced_licenses",
1617        value_shape: "array<string>",
1618        presence: "Emitted only when non-empty.",
1619        meaning: "License keys replaced by local overlays or custom dataset input.",
1620    },
1621];
1622
1623const PARTY_FIELDS: &[OutputFieldDoc] = &[
1624    OutputFieldDoc {
1625        json_name: "type",
1626        rust_field: "r#type",
1627        value_shape: "string | null",
1628        presence: "Always emitted.",
1629        meaning: "Normalized party type such as person or organization.",
1630    },
1631    OutputFieldDoc {
1632        json_name: "role",
1633        rust_field: "role",
1634        value_shape: "string | null",
1635        presence: "Always emitted.",
1636        meaning: "Role of the party on the package or metadata record.",
1637    },
1638    OutputFieldDoc {
1639        json_name: "name",
1640        rust_field: "name",
1641        value_shape: "string | null",
1642        presence: "Always emitted.",
1643        meaning: "Human-readable party name.",
1644    },
1645    OutputFieldDoc {
1646        json_name: "email",
1647        rust_field: "email",
1648        value_shape: "string | null",
1649        presence: "Always emitted.",
1650        meaning: "Party email address.",
1651    },
1652    OutputFieldDoc {
1653        json_name: "url",
1654        rust_field: "url",
1655        value_shape: "string | null",
1656        presence: "Always emitted.",
1657        meaning: "Party homepage or profile URL.",
1658    },
1659    OutputFieldDoc {
1660        json_name: "organization",
1661        rust_field: "organization",
1662        value_shape: "string | null",
1663        presence: "Emitted only when available.",
1664        meaning: "Owning organization for the party, when captured separately from the party name.",
1665    },
1666    OutputFieldDoc {
1667        json_name: "organization_url",
1668        rust_field: "organization_url",
1669        value_shape: "string | null",
1670        presence: "Emitted only when available.",
1671        meaning: "Owning organization URL for the party.",
1672    },
1673    OutputFieldDoc {
1674        json_name: "timezone",
1675        rust_field: "timezone",
1676        value_shape: "string | null",
1677        presence: "Emitted only when available.",
1678        meaning: "Timezone associated with the party metadata, when available.",
1679    },
1680];
1681
1682const FILE_REFERENCE_FIELDS: &[OutputFieldDoc] = &[
1683    OutputFieldDoc {
1684        json_name: "path",
1685        rust_field: "path",
1686        value_shape: "string",
1687        presence: "Always emitted.",
1688        meaning: "Referenced file path preserved on the package/file-reference surface.",
1689    },
1690    OutputFieldDoc {
1691        json_name: "size",
1692        rust_field: "size",
1693        value_shape: "integer | null",
1694        presence: "Emitted only when available.",
1695        meaning: "Referenced file size when known.",
1696    },
1697    OutputFieldDoc {
1698        json_name: "sha1",
1699        rust_field: "sha1",
1700        value_shape: "string | null",
1701        presence: "Always emitted.",
1702        meaning: "Referenced file SHA-1 checksum when known.",
1703    },
1704    OutputFieldDoc {
1705        json_name: "md5",
1706        rust_field: "md5",
1707        value_shape: "string | null",
1708        presence: "Always emitted.",
1709        meaning: "Referenced file MD5 checksum when known.",
1710    },
1711    OutputFieldDoc {
1712        json_name: "sha256",
1713        rust_field: "sha256",
1714        value_shape: "string | null",
1715        presence: "Always emitted.",
1716        meaning: "Referenced file SHA-256 checksum when known.",
1717    },
1718    OutputFieldDoc {
1719        json_name: "sha512",
1720        rust_field: "sha512",
1721        value_shape: "string | null",
1722        presence: "Always emitted.",
1723        meaning: "Referenced file SHA-512 checksum when known.",
1724    },
1725    OutputFieldDoc {
1726        json_name: "extra_data",
1727        rust_field: "extra_data",
1728        value_shape: "object",
1729        presence: "Always emitted.",
1730        meaning: "Additional metadata preserved on the referenced-file row.",
1731    },
1732];
1733
1734const LICENSE_POLICY_ENTRY_FIELDS: &[OutputFieldDoc] = &[
1735    OutputFieldDoc {
1736        json_name: "license_key",
1737        rust_field: "license_key",
1738        value_shape: "string",
1739        presence: "Always emitted.",
1740        meaning: "License key this policy entry applies to.",
1741    },
1742    OutputFieldDoc {
1743        json_name: "label",
1744        rust_field: "label",
1745        value_shape: "string",
1746        presence: "Always emitted.",
1747        meaning: "Human-facing policy label for the license.",
1748    },
1749    OutputFieldDoc {
1750        json_name: "color_code",
1751        rust_field: "color_code",
1752        value_shape: "string",
1753        presence: "Always emitted.",
1754        meaning: "Color code used by policy-aware outputs or UIs.",
1755    },
1756    OutputFieldDoc {
1757        json_name: "icon",
1758        rust_field: "icon",
1759        value_shape: "string",
1760        presence: "Always emitted.",
1761        meaning: "Icon identifier used by policy-aware outputs or UIs.",
1762    },
1763];
1764
1765const AUTHOR_FIELDS: &[OutputFieldDoc] = &[
1766    OutputFieldDoc {
1767        json_name: "author",
1768        rust_field: "author",
1769        value_shape: "string",
1770        presence: "Always emitted.",
1771        meaning: "Extracted author string.",
1772    },
1773    OutputFieldDoc {
1774        json_name: "start_line",
1775        rust_field: "start_line",
1776        value_shape: "integer",
1777        presence: "Always emitted.",
1778        meaning: "First line where the author evidence appeared.",
1779    },
1780    OutputFieldDoc {
1781        json_name: "end_line",
1782        rust_field: "end_line",
1783        value_shape: "integer",
1784        presence: "Always emitted.",
1785        meaning: "Last line where the author evidence appeared.",
1786    },
1787];
1788
1789const COPYRIGHT_FIELDS: &[OutputFieldDoc] = &[
1790    OutputFieldDoc {
1791        json_name: "copyright",
1792        rust_field: "copyright",
1793        value_shape: "string",
1794        presence: "Always emitted.",
1795        meaning: "Rendered copyright string, using native or ScanCode compatibility mode as selected.",
1796    },
1797    OutputFieldDoc {
1798        json_name: "start_line",
1799        rust_field: "start_line",
1800        value_shape: "integer",
1801        presence: "Always emitted.",
1802        meaning: "First line where the copyright evidence appeared.",
1803    },
1804    OutputFieldDoc {
1805        json_name: "end_line",
1806        rust_field: "end_line",
1807        value_shape: "integer",
1808        presence: "Always emitted.",
1809        meaning: "Last line where the copyright evidence appeared.",
1810    },
1811];
1812
1813const EMAIL_FIELDS: &[OutputFieldDoc] = &[
1814    OutputFieldDoc {
1815        json_name: "email",
1816        rust_field: "email",
1817        value_shape: "string",
1818        presence: "Always emitted.",
1819        meaning: "Extracted email address.",
1820    },
1821    OutputFieldDoc {
1822        json_name: "start_line",
1823        rust_field: "start_line",
1824        value_shape: "integer",
1825        presence: "Always emitted.",
1826        meaning: "First line where the email evidence appeared.",
1827    },
1828    OutputFieldDoc {
1829        json_name: "end_line",
1830        rust_field: "end_line",
1831        value_shape: "integer",
1832        presence: "Always emitted.",
1833        meaning: "Last line where the email evidence appeared.",
1834    },
1835];
1836
1837const HOLDER_FIELDS: &[OutputFieldDoc] = &[
1838    OutputFieldDoc {
1839        json_name: "holder",
1840        rust_field: "holder",
1841        value_shape: "string",
1842        presence: "Always emitted.",
1843        meaning: "Extracted copyright holder string.",
1844    },
1845    OutputFieldDoc {
1846        json_name: "start_line",
1847        rust_field: "start_line",
1848        value_shape: "integer",
1849        presence: "Always emitted.",
1850        meaning: "First line where the holder evidence appeared.",
1851    },
1852    OutputFieldDoc {
1853        json_name: "end_line",
1854        rust_field: "end_line",
1855        value_shape: "integer",
1856        presence: "Always emitted.",
1857        meaning: "Last line where the holder evidence appeared.",
1858    },
1859];
1860
1861const URL_FIELDS: &[OutputFieldDoc] = &[
1862    OutputFieldDoc {
1863        json_name: "url",
1864        rust_field: "url",
1865        value_shape: "string",
1866        presence: "Always emitted.",
1867        meaning: "Extracted URL string.",
1868    },
1869    OutputFieldDoc {
1870        json_name: "start_line",
1871        rust_field: "start_line",
1872        value_shape: "integer",
1873        presence: "Always emitted.",
1874        meaning: "First line where the URL evidence appeared.",
1875    },
1876    OutputFieldDoc {
1877        json_name: "end_line",
1878        rust_field: "end_line",
1879        value_shape: "integer",
1880        presence: "Always emitted.",
1881        meaning: "Last line where the URL evidence appeared.",
1882    },
1883];
1884
1885const LICENSE_DETECTION_FIELDS: &[OutputFieldDoc] = &[
1886    OutputFieldDoc {
1887        json_name: "license_expression",
1888        rust_field: "license_expression",
1889        value_shape: "string",
1890        presence: "Always emitted.",
1891        meaning: "Grouped license expression for the detection block.",
1892    },
1893    OutputFieldDoc {
1894        json_name: "license_expression_spdx",
1895        rust_field: "license_expression_spdx",
1896        value_shape: "string",
1897        presence: "Always emitted.",
1898        meaning: "SPDX-form expression for the detection block.",
1899    },
1900    OutputFieldDoc {
1901        json_name: "matches",
1902        rust_field: "matches",
1903        value_shape: "array<object>",
1904        presence: "Always emitted.",
1905        meaning: "Match records that contributed to this grouped file- or package-level detection.",
1906    },
1907    OutputFieldDoc {
1908        json_name: "detection_log",
1909        rust_field: "detection_log",
1910        value_shape: "array<string>",
1911        presence: "Emitted only when non-empty.",
1912        meaning: "Notes explaining post-processing or grouping decisions for this detection.",
1913    },
1914    OutputFieldDoc {
1915        json_name: "identifier",
1916        rust_field: "identifier",
1917        value_shape: "string | null",
1918        presence: "Always emitted.",
1919        meaning: "Stable detection identifier when available.",
1920    },
1921];
1922
1923const MATCH_FIELDS: &[OutputFieldDoc] = &[
1924    OutputFieldDoc {
1925        json_name: "license_expression",
1926        rust_field: "license_expression",
1927        value_shape: "string",
1928        presence: "Always emitted.",
1929        meaning: "License expression assigned to this individual match.",
1930    },
1931    OutputFieldDoc {
1932        json_name: "license_expression_spdx",
1933        rust_field: "license_expression_spdx",
1934        value_shape: "string",
1935        presence: "Always emitted.",
1936        meaning: "SPDX-form expression assigned to this individual match.",
1937    },
1938    OutputFieldDoc {
1939        json_name: "from_file",
1940        rust_field: "from_file",
1941        value_shape: "string | null",
1942        presence: "Always emitted.",
1943        meaning: "Origin file path associated with the match record.",
1944    },
1945    OutputFieldDoc {
1946        json_name: "start_line",
1947        rust_field: "start_line",
1948        value_shape: "integer",
1949        presence: "Always emitted.",
1950        meaning: "First line covered by the match.",
1951    },
1952    OutputFieldDoc {
1953        json_name: "end_line",
1954        rust_field: "end_line",
1955        value_shape: "integer",
1956        presence: "Always emitted.",
1957        meaning: "Last line covered by the match.",
1958    },
1959    OutputFieldDoc {
1960        json_name: "matcher",
1961        rust_field: "matcher",
1962        value_shape: "string | null",
1963        presence: "Emitted only when available.",
1964        meaning: "Matcher kind that produced the match.",
1965    },
1966    OutputFieldDoc {
1967        json_name: "score",
1968        rust_field: "score",
1969        value_shape: "number",
1970        presence: "Always emitted.",
1971        meaning: "Match score on the public output scale.",
1972    },
1973    OutputFieldDoc {
1974        json_name: "matched_length",
1975        rust_field: "matched_length",
1976        value_shape: "integer | null",
1977        presence: "Emitted only when available.",
1978        meaning: "Matched token/text length when tracked.",
1979    },
1980    OutputFieldDoc {
1981        json_name: "match_coverage",
1982        rust_field: "match_coverage",
1983        value_shape: "number | null",
1984        presence: "Emitted only when available.",
1985        meaning: "Coverage ratio for the match when tracked.",
1986    },
1987    OutputFieldDoc {
1988        json_name: "rule_relevance",
1989        rust_field: "rule_relevance",
1990        value_shape: "integer | null",
1991        presence: "Emitted only when available.",
1992        meaning: "Rule relevance score when tracked.",
1993    },
1994    OutputFieldDoc {
1995        json_name: "rule_identifier",
1996        rust_field: "rule_identifier",
1997        value_shape: "string | null",
1998        presence: "Emitted only when available.",
1999        meaning: "Identifier of the matched rule when available.",
2000    },
2001    OutputFieldDoc {
2002        json_name: "rule_url",
2003        rust_field: "rule_url",
2004        value_shape: "string | null",
2005        presence: "Always emitted.",
2006        meaning: "Rule URL when available.",
2007    },
2008    OutputFieldDoc {
2009        json_name: "matched_text",
2010        rust_field: "matched_text",
2011        value_shape: "string | null",
2012        presence: "Emitted only when available.",
2013        meaning: "Matched text payload when text output is enabled.",
2014    },
2015    OutputFieldDoc {
2016        json_name: "matched_text_diagnostics",
2017        rust_field: "matched_text_diagnostics",
2018        value_shape: "string | null",
2019        presence: "Emitted only when available.",
2020        meaning: "Diagnostic rendering of the matched text when enabled.",
2021    },
2022    OutputFieldDoc {
2023        json_name: "referenced_filenames",
2024        rust_field: "referenced_filenames",
2025        value_shape: "array<string> | null",
2026        presence: "Emitted only when available.",
2027        meaning: "Referenced filenames captured on the matched rule when applicable.",
2028    },
2029];
2030
2031const LICENSE_REFERENCE_FIELDS: &[OutputFieldDoc] = &[
2032    OutputFieldDoc {
2033        json_name: "key",
2034        rust_field: "key",
2035        value_shape: "string | null",
2036        presence: "Emitted only when available.",
2037        meaning: "Primary ScanCode-style license key when one is available for the reference block.",
2038    },
2039    OutputFieldDoc {
2040        json_name: "language",
2041        rust_field: "language",
2042        value_shape: "string | null",
2043        presence: "Emitted only when available.",
2044        meaning: "Language tag for the referenced license text when the license reference is language-specific.",
2045    },
2046    OutputFieldDoc {
2047        json_name: "name",
2048        rust_field: "name",
2049        value_shape: "string",
2050        presence: "Always emitted.",
2051        meaning: "Canonical human-facing name of the referenced license.",
2052    },
2053    OutputFieldDoc {
2054        json_name: "short_name",
2055        rust_field: "short_name",
2056        value_shape: "string",
2057        presence: "Always emitted.",
2058        meaning: "Short display name of the referenced license.",
2059    },
2060    OutputFieldDoc {
2061        json_name: "owner",
2062        rust_field: "owner",
2063        value_shape: "string | null",
2064        presence: "Emitted only when available.",
2065        meaning: "Owning organization or steward of the referenced license, when captured.",
2066    },
2067    OutputFieldDoc {
2068        json_name: "homepage_url",
2069        rust_field: "homepage_url",
2070        value_shape: "string | null",
2071        presence: "Emitted only when available.",
2072        meaning: "Homepage URL for the referenced license.",
2073    },
2074    OutputFieldDoc {
2075        json_name: "spdx_license_key",
2076        rust_field: "spdx_license_key",
2077        value_shape: "string",
2078        presence: "Always emitted.",
2079        meaning: "Primary SPDX license key associated with the referenced license.",
2080    },
2081    OutputFieldDoc {
2082        json_name: "other_spdx_license_keys",
2083        rust_field: "other_spdx_license_keys",
2084        value_shape: "array<string>",
2085        presence: "Emitted only when non-empty.",
2086        meaning: "Additional SPDX license keys associated with the same referenced license.",
2087    },
2088    OutputFieldDoc {
2089        json_name: "osi_license_key",
2090        rust_field: "osi_license_key",
2091        value_shape: "string | null",
2092        presence: "Emitted only when available.",
2093        meaning: "OSI license key when the referenced license is recognized by OSI.",
2094    },
2095    OutputFieldDoc {
2096        json_name: "text_urls",
2097        rust_field: "text_urls",
2098        value_shape: "array<string>",
2099        presence: "Emitted only when non-empty.",
2100        meaning: "URLs to known license text sources for this referenced license.",
2101    },
2102    OutputFieldDoc {
2103        json_name: "osi_url",
2104        rust_field: "osi_url",
2105        value_shape: "string | null",
2106        presence: "Emitted only when available.",
2107        meaning: "OSI detail page URL for the referenced license.",
2108    },
2109    OutputFieldDoc {
2110        json_name: "faq_url",
2111        rust_field: "faq_url",
2112        value_shape: "string | null",
2113        presence: "Emitted only when available.",
2114        meaning: "FAQ URL for the referenced license.",
2115    },
2116    OutputFieldDoc {
2117        json_name: "other_urls",
2118        rust_field: "other_urls",
2119        value_shape: "array<string>",
2120        presence: "Emitted only when non-empty.",
2121        meaning: "Additional URLs associated with the referenced license.",
2122    },
2123    OutputFieldDoc {
2124        json_name: "category",
2125        rust_field: "category",
2126        value_shape: "string | null",
2127        presence: "Emitted only when available.",
2128        meaning: "License category label, when the license data classifies it.",
2129    },
2130    OutputFieldDoc {
2131        json_name: "is_exception",
2132        rust_field: "is_exception",
2133        value_shape: "boolean",
2134        presence: "Always emitted.",
2135        meaning: "Whether the referenced license is an exception rather than a standalone license.",
2136    },
2137    OutputFieldDoc {
2138        json_name: "is_unknown",
2139        rust_field: "is_unknown",
2140        value_shape: "boolean",
2141        presence: "Always emitted.",
2142        meaning: "Whether the referenced license is treated as an unknown or placeholder license.",
2143    },
2144    OutputFieldDoc {
2145        json_name: "is_generic",
2146        rust_field: "is_generic",
2147        value_shape: "boolean",
2148        presence: "Always emitted.",
2149        meaning: "Whether the referenced license is generic rather than a specific named license.",
2150    },
2151    OutputFieldDoc {
2152        json_name: "notes",
2153        rust_field: "notes",
2154        value_shape: "string | null",
2155        presence: "Emitted only when available.",
2156        meaning: "Additional notes carried by the referenced license record.",
2157    },
2158    OutputFieldDoc {
2159        json_name: "minimum_coverage",
2160        rust_field: "minimum_coverage",
2161        value_shape: "integer | null",
2162        presence: "Emitted only when available.",
2163        meaning: "Minimum coverage threshold associated with the referenced license, when specified.",
2164    },
2165    OutputFieldDoc {
2166        json_name: "standard_notice",
2167        rust_field: "standard_notice",
2168        value_shape: "string | null",
2169        presence: "Emitted only when available.",
2170        meaning: "Standard notice text associated with the referenced license.",
2171    },
2172    OutputFieldDoc {
2173        json_name: "ignorable_copyrights",
2174        rust_field: "ignorable_copyrights",
2175        value_shape: "array<string>",
2176        presence: "Emitted only when non-empty.",
2177        meaning: "Copyright strings considered ignorable for this referenced license.",
2178    },
2179    OutputFieldDoc {
2180        json_name: "ignorable_holders",
2181        rust_field: "ignorable_holders",
2182        value_shape: "array<string>",
2183        presence: "Emitted only when non-empty.",
2184        meaning: "Holder strings considered ignorable for this referenced license.",
2185    },
2186    OutputFieldDoc {
2187        json_name: "ignorable_authors",
2188        rust_field: "ignorable_authors",
2189        value_shape: "array<string>",
2190        presence: "Emitted only when non-empty.",
2191        meaning: "Author strings considered ignorable for this referenced license.",
2192    },
2193    OutputFieldDoc {
2194        json_name: "ignorable_urls",
2195        rust_field: "ignorable_urls",
2196        value_shape: "array<string>",
2197        presence: "Emitted only when non-empty.",
2198        meaning: "URL strings considered ignorable for this referenced license.",
2199    },
2200    OutputFieldDoc {
2201        json_name: "ignorable_emails",
2202        rust_field: "ignorable_emails",
2203        value_shape: "array<string>",
2204        presence: "Emitted only when non-empty.",
2205        meaning: "Email strings considered ignorable for this referenced license.",
2206    },
2207    OutputFieldDoc {
2208        json_name: "scancode_url",
2209        rust_field: "scancode_url",
2210        value_shape: "string | null",
2211        presence: "Emitted only when available.",
2212        meaning: "ScanCode reference URL for this license, when available.",
2213    },
2214    OutputFieldDoc {
2215        json_name: "licensedb_url",
2216        rust_field: "licensedb_url",
2217        value_shape: "string | null",
2218        presence: "Emitted only when available.",
2219        meaning: "LicenseDB URL for this license, when available.",
2220    },
2221    OutputFieldDoc {
2222        json_name: "spdx_url",
2223        rust_field: "spdx_url",
2224        value_shape: "string | null",
2225        presence: "Emitted only when available.",
2226        meaning: "SPDX reference URL for this license, when available.",
2227    },
2228    OutputFieldDoc {
2229        json_name: "text",
2230        rust_field: "text",
2231        value_shape: "string",
2232        presence: "Always emitted.",
2233        meaning: "Canonical license text payload preserved on the reference block.",
2234    },
2235];
2236
2237const LICENSE_RULE_REFERENCE_FIELDS: &[OutputFieldDoc] = &[
2238    OutputFieldDoc {
2239        json_name: "identifier",
2240        rust_field: "identifier",
2241        value_shape: "string",
2242        presence: "Always emitted.",
2243        meaning: "Stable identifier of the referenced license rule.",
2244    },
2245    OutputFieldDoc {
2246        json_name: "license_expression",
2247        rust_field: "license_expression",
2248        value_shape: "string",
2249        presence: "Always emitted.",
2250        meaning: "License expression associated with the referenced rule.",
2251    },
2252    OutputFieldDoc {
2253        json_name: "is_license_text",
2254        rust_field: "is_license_text",
2255        value_shape: "boolean",
2256        presence: "Always emitted.",
2257        meaning: "Whether the rule is classified as license-text evidence.",
2258    },
2259    OutputFieldDoc {
2260        json_name: "is_license_notice",
2261        rust_field: "is_license_notice",
2262        value_shape: "boolean",
2263        presence: "Always emitted.",
2264        meaning: "Whether the rule is classified as license-notice evidence.",
2265    },
2266    OutputFieldDoc {
2267        json_name: "is_license_reference",
2268        rust_field: "is_license_reference",
2269        value_shape: "boolean",
2270        presence: "Always emitted.",
2271        meaning: "Whether the rule is classified as license-reference evidence.",
2272    },
2273    OutputFieldDoc {
2274        json_name: "is_license_tag",
2275        rust_field: "is_license_tag",
2276        value_shape: "boolean",
2277        presence: "Always emitted.",
2278        meaning: "Whether the rule is classified as license-tag evidence.",
2279    },
2280    OutputFieldDoc {
2281        json_name: "is_license_clue",
2282        rust_field: "is_license_clue",
2283        value_shape: "boolean",
2284        presence: "Always emitted.",
2285        meaning: "Whether the rule is classified as clue-only evidence.",
2286    },
2287    OutputFieldDoc {
2288        json_name: "is_license_intro",
2289        rust_field: "is_license_intro",
2290        value_shape: "boolean",
2291        presence: "Always emitted.",
2292        meaning: "Whether the rule is classified as introductory license wording.",
2293    },
2294    OutputFieldDoc {
2295        json_name: "language",
2296        rust_field: "language",
2297        value_shape: "string | null",
2298        presence: "Emitted only when available.",
2299        meaning: "Language tag for the referenced rule when the rule is language-specific.",
2300    },
2301    OutputFieldDoc {
2302        json_name: "rule_url",
2303        rust_field: "rule_url",
2304        value_shape: "string | null",
2305        presence: "Emitted only when available.",
2306        meaning: "Reference URL for the rule, when available.",
2307    },
2308    OutputFieldDoc {
2309        json_name: "is_required_phrase",
2310        rust_field: "is_required_phrase",
2311        value_shape: "boolean",
2312        presence: "Always emitted.",
2313        meaning: "Whether the rule is a required-phrase rule.",
2314    },
2315    OutputFieldDoc {
2316        json_name: "skip_for_required_phrase_generation",
2317        rust_field: "skip_for_required_phrase_generation",
2318        value_shape: "boolean",
2319        presence: "Always emitted.",
2320        meaning: "Whether this rule should be excluded when deriving required-phrase rules automatically.",
2321    },
2322    OutputFieldDoc {
2323        json_name: "replaced_by",
2324        rust_field: "replaced_by",
2325        value_shape: "array<string>",
2326        presence: "Emitted only when non-empty.",
2327        meaning: "Rule identifiers that supersede this rule.",
2328    },
2329    OutputFieldDoc {
2330        json_name: "is_continuous",
2331        rust_field: "is_continuous",
2332        value_shape: "boolean",
2333        presence: "Always emitted.",
2334        meaning: "Whether the rule expects continuous text rather than discontinuous matches.",
2335    },
2336    OutputFieldDoc {
2337        json_name: "is_synthetic",
2338        rust_field: "is_synthetic",
2339        value_shape: "boolean",
2340        presence: "Always emitted.",
2341        meaning: "Whether the rule was synthesized rather than sourced directly from curated reference text.",
2342    },
2343    OutputFieldDoc {
2344        json_name: "is_from_license",
2345        rust_field: "is_from_license",
2346        value_shape: "boolean",
2347        presence: "Always emitted.",
2348        meaning: "Whether the rule was derived directly from a license text record.",
2349    },
2350    OutputFieldDoc {
2351        json_name: "length",
2352        rust_field: "length",
2353        value_shape: "integer",
2354        presence: "Always emitted.",
2355        meaning: "Rule length on the public rule-reference surface.",
2356    },
2357    OutputFieldDoc {
2358        json_name: "relevance",
2359        rust_field: "relevance",
2360        value_shape: "integer | null",
2361        presence: "Emitted only when available.",
2362        meaning: "Rule relevance score, when present.",
2363    },
2364    OutputFieldDoc {
2365        json_name: "minimum_coverage",
2366        rust_field: "minimum_coverage",
2367        value_shape: "integer | null",
2368        presence: "Emitted only when available.",
2369        meaning: "Minimum coverage threshold associated with the rule, when specified.",
2370    },
2371    OutputFieldDoc {
2372        json_name: "referenced_filenames",
2373        rust_field: "referenced_filenames",
2374        value_shape: "array<string>",
2375        presence: "Emitted only when non-empty.",
2376        meaning: "Referenced filenames attached to the rule metadata.",
2377    },
2378    OutputFieldDoc {
2379        json_name: "notes",
2380        rust_field: "notes",
2381        value_shape: "string | null",
2382        presence: "Emitted only when available.",
2383        meaning: "Additional notes carried by the rule reference.",
2384    },
2385    OutputFieldDoc {
2386        json_name: "ignorable_copyrights",
2387        rust_field: "ignorable_copyrights",
2388        value_shape: "array<string>",
2389        presence: "Emitted only when non-empty.",
2390        meaning: "Copyright strings considered ignorable for this rule.",
2391    },
2392    OutputFieldDoc {
2393        json_name: "ignorable_holders",
2394        rust_field: "ignorable_holders",
2395        value_shape: "array<string>",
2396        presence: "Emitted only when non-empty.",
2397        meaning: "Holder strings considered ignorable for this rule.",
2398    },
2399    OutputFieldDoc {
2400        json_name: "ignorable_authors",
2401        rust_field: "ignorable_authors",
2402        value_shape: "array<string>",
2403        presence: "Emitted only when non-empty.",
2404        meaning: "Author strings considered ignorable for this rule.",
2405    },
2406    OutputFieldDoc {
2407        json_name: "ignorable_urls",
2408        rust_field: "ignorable_urls",
2409        value_shape: "array<string>",
2410        presence: "Emitted only when non-empty.",
2411        meaning: "URL strings considered ignorable for this rule.",
2412    },
2413    OutputFieldDoc {
2414        json_name: "ignorable_emails",
2415        rust_field: "ignorable_emails",
2416        value_shape: "array<string>",
2417        presence: "Emitted only when non-empty.",
2418        meaning: "Email strings considered ignorable for this rule.",
2419    },
2420    OutputFieldDoc {
2421        json_name: "text",
2422        rust_field: "text",
2423        value_shape: "string | null",
2424        presence: "Emitted only when available.",
2425        meaning: "Canonical rule text payload when the reference includes it.",
2426    },
2427];
2428
2429const RESOLVED_PACKAGE_FIELDS: &[OutputFieldDoc] = &[
2430    OutputFieldDoc {
2431        json_name: "type",
2432        rust_field: "package_type",
2433        value_shape: "string",
2434        presence: "Always emitted.",
2435        meaning: "Package ecosystem/type identifier on the resolved-package payload.",
2436    },
2437    OutputFieldDoc {
2438        json_name: "namespace",
2439        rust_field: "namespace",
2440        value_shape: "string",
2441        presence: "Always emitted.",
2442        meaning: "Resolved package namespace.",
2443    },
2444    OutputFieldDoc {
2445        json_name: "name",
2446        rust_field: "name",
2447        value_shape: "string",
2448        presence: "Always emitted.",
2449        meaning: "Resolved package name.",
2450    },
2451    OutputFieldDoc {
2452        json_name: "version",
2453        rust_field: "version",
2454        value_shape: "string",
2455        presence: "Always emitted.",
2456        meaning: "Resolved package version.",
2457    },
2458    OutputFieldDoc {
2459        json_name: "qualifiers",
2460        rust_field: "qualifiers",
2461        value_shape: "object",
2462        presence: "Always emitted.",
2463        meaning: "PURL-style qualifier key/value pairs on the resolved-package payload.",
2464    },
2465    OutputFieldDoc {
2466        json_name: "subpath",
2467        rust_field: "subpath",
2468        value_shape: "string | null",
2469        presence: "Always emitted.",
2470        meaning: "Resolved package subpath, when available.",
2471    },
2472    OutputFieldDoc {
2473        json_name: "primary_language",
2474        rust_field: "primary_language",
2475        value_shape: "string | null",
2476        presence: "Always emitted.",
2477        meaning: "Primary language associated with the resolved package.",
2478    },
2479    OutputFieldDoc {
2480        json_name: "description",
2481        rust_field: "description",
2482        value_shape: "string | null",
2483        presence: "Always emitted.",
2484        meaning: "Resolved package description.",
2485    },
2486    OutputFieldDoc {
2487        json_name: "release_date",
2488        rust_field: "release_date",
2489        value_shape: "string | null",
2490        presence: "Always emitted.",
2491        meaning: "Resolved package release date.",
2492    },
2493    OutputFieldDoc {
2494        json_name: "parties",
2495        rust_field: "parties",
2496        value_shape: "array<object>",
2497        presence: "Always emitted.",
2498        meaning: "Party records attached to the resolved package.",
2499    },
2500    OutputFieldDoc {
2501        json_name: "keywords",
2502        rust_field: "keywords",
2503        value_shape: "array<string>",
2504        presence: "Always emitted.",
2505        meaning: "Keywords attached to the resolved package.",
2506    },
2507    OutputFieldDoc {
2508        json_name: "homepage_url",
2509        rust_field: "homepage_url",
2510        value_shape: "string | null",
2511        presence: "Always emitted.",
2512        meaning: "Resolved package homepage URL.",
2513    },
2514    OutputFieldDoc {
2515        json_name: "download_url",
2516        rust_field: "download_url",
2517        value_shape: "string | null",
2518        presence: "Always emitted.",
2519        meaning: "Resolved package download URL.",
2520    },
2521    OutputFieldDoc {
2522        json_name: "size",
2523        rust_field: "size",
2524        value_shape: "integer | null",
2525        presence: "Always emitted.",
2526        meaning: "Resolved package size when known.",
2527    },
2528    OutputFieldDoc {
2529        json_name: "sha1",
2530        rust_field: "sha1",
2531        value_shape: "string | null",
2532        presence: "Always emitted.",
2533        meaning: "Resolved package SHA-1 checksum when known.",
2534    },
2535    OutputFieldDoc {
2536        json_name: "md5",
2537        rust_field: "md5",
2538        value_shape: "string | null",
2539        presence: "Always emitted.",
2540        meaning: "Resolved package MD5 checksum when known.",
2541    },
2542    OutputFieldDoc {
2543        json_name: "sha256",
2544        rust_field: "sha256",
2545        value_shape: "string | null",
2546        presence: "Always emitted.",
2547        meaning: "Resolved package SHA-256 checksum when known.",
2548    },
2549    OutputFieldDoc {
2550        json_name: "sha512",
2551        rust_field: "sha512",
2552        value_shape: "string | null",
2553        presence: "Always emitted.",
2554        meaning: "Resolved package SHA-512 checksum when known.",
2555    },
2556    OutputFieldDoc {
2557        json_name: "bug_tracking_url",
2558        rust_field: "bug_tracking_url",
2559        value_shape: "string | null",
2560        presence: "Always emitted.",
2561        meaning: "Resolved package bug-tracker URL.",
2562    },
2563    OutputFieldDoc {
2564        json_name: "code_view_url",
2565        rust_field: "code_view_url",
2566        value_shape: "string | null",
2567        presence: "Always emitted.",
2568        meaning: "Resolved package code-browsing URL.",
2569    },
2570    OutputFieldDoc {
2571        json_name: "vcs_url",
2572        rust_field: "vcs_url",
2573        value_shape: "string | null",
2574        presence: "Always emitted.",
2575        meaning: "Resolved package VCS URL.",
2576    },
2577    OutputFieldDoc {
2578        json_name: "copyright",
2579        rust_field: "copyright",
2580        value_shape: "string | null",
2581        presence: "Always emitted.",
2582        meaning: "Resolved package copyright string.",
2583    },
2584    OutputFieldDoc {
2585        json_name: "holder",
2586        rust_field: "holder",
2587        value_shape: "string | null",
2588        presence: "Always emitted.",
2589        meaning: "Resolved package holder string.",
2590    },
2591    OutputFieldDoc {
2592        json_name: "declared_license_expression",
2593        rust_field: "declared_license_expression",
2594        value_shape: "string | null",
2595        presence: "Always emitted.",
2596        meaning: "Primary declared license expression on the resolved-package payload.",
2597    },
2598    OutputFieldDoc {
2599        json_name: "declared_license_expression_spdx",
2600        rust_field: "declared_license_expression_spdx",
2601        value_shape: "string | null",
2602        presence: "Always emitted.",
2603        meaning: "SPDX-form primary declared license expression on the resolved-package payload.",
2604    },
2605    OutputFieldDoc {
2606        json_name: "license_detections",
2607        rust_field: "license_detections",
2608        value_shape: "array<object>",
2609        presence: "Always emitted.",
2610        meaning: "License detections attached to the resolved-package payload.",
2611    },
2612    OutputFieldDoc {
2613        json_name: "other_license_expression",
2614        rust_field: "other_license_expression",
2615        value_shape: "string | null",
2616        presence: "Always emitted.",
2617        meaning: "Auxiliary non-primary license expression lane on the resolved-package payload.",
2618    },
2619    OutputFieldDoc {
2620        json_name: "other_license_expression_spdx",
2621        rust_field: "other_license_expression_spdx",
2622        value_shape: "string | null",
2623        presence: "Always emitted.",
2624        meaning: "SPDX-form auxiliary non-primary license expression lane on the resolved-package payload.",
2625    },
2626    OutputFieldDoc {
2627        json_name: "other_license_detections",
2628        rust_field: "other_license_detections",
2629        value_shape: "array<object>",
2630        presence: "Always emitted.",
2631        meaning: "Auxiliary license detections attached to the resolved-package payload.",
2632    },
2633    OutputFieldDoc {
2634        json_name: "extracted_license_statement",
2635        rust_field: "extracted_license_statement",
2636        value_shape: "string | null",
2637        presence: "Always emitted.",
2638        meaning: "Raw extracted license statement on the resolved-package payload.",
2639    },
2640    OutputFieldDoc {
2641        json_name: "notice_text",
2642        rust_field: "notice_text",
2643        value_shape: "string | null",
2644        presence: "Always emitted.",
2645        meaning: "Resolved package notice text.",
2646    },
2647    OutputFieldDoc {
2648        json_name: "source_packages",
2649        rust_field: "source_packages",
2650        value_shape: "array<string>",
2651        presence: "Always emitted.",
2652        meaning: "Referenced source-package identifiers associated with the resolved package.",
2653    },
2654    OutputFieldDoc {
2655        json_name: "file_references",
2656        rust_field: "file_references",
2657        value_shape: "array<object>",
2658        presence: "Always emitted.",
2659        meaning: "Referenced-file rows attached to the resolved package.",
2660    },
2661    OutputFieldDoc {
2662        json_name: "is_private",
2663        rust_field: "is_private",
2664        value_shape: "boolean",
2665        presence: "Always emitted.",
2666        meaning: "Private/public signal on the resolved-package payload.",
2667    },
2668    OutputFieldDoc {
2669        json_name: "is_virtual",
2670        rust_field: "is_virtual",
2671        value_shape: "boolean",
2672        presence: "Always emitted.",
2673        meaning: "Virtual/synthetic signal on the resolved-package payload.",
2674    },
2675    OutputFieldDoc {
2676        json_name: "extra_data",
2677        rust_field: "extra_data",
2678        value_shape: "object",
2679        presence: "Always emitted.",
2680        meaning: "Datasource-specific structured metadata preserved on the resolved-package payload.",
2681    },
2682    OutputFieldDoc {
2683        json_name: "dependencies",
2684        rust_field: "dependencies",
2685        value_shape: "array<object>",
2686        presence: "Always emitted.",
2687        meaning: "Dependency rows nested under the resolved-package payload.",
2688    },
2689    OutputFieldDoc {
2690        json_name: "repository_homepage_url",
2691        rust_field: "repository_homepage_url",
2692        value_shape: "string | null",
2693        presence: "Always emitted.",
2694        meaning: "Repository homepage URL for the resolved package.",
2695    },
2696    OutputFieldDoc {
2697        json_name: "repository_download_url",
2698        rust_field: "repository_download_url",
2699        value_shape: "string | null",
2700        presence: "Always emitted.",
2701        meaning: "Repository download URL for the resolved package.",
2702    },
2703    OutputFieldDoc {
2704        json_name: "api_data_url",
2705        rust_field: "api_data_url",
2706        value_shape: "string | null",
2707        presence: "Always emitted.",
2708        meaning: "API data URL for the resolved package.",
2709    },
2710    OutputFieldDoc {
2711        json_name: "datasource_id",
2712        rust_field: "datasource_id",
2713        value_shape: "string | null",
2714        presence: "Always emitted.",
2715        meaning: "Single datasource identifier associated with the resolved-package payload, when available.",
2716    },
2717    OutputFieldDoc {
2718        json_name: "purl",
2719        rust_field: "purl",
2720        value_shape: "string | null",
2721        presence: "Always emitted.",
2722        meaning: "Package URL for the resolved package.",
2723    },
2724];
2725
2726const EMPTY_FIELDS: &[OutputFieldDoc] = &[];
2727
2728const DOCUMENTED_TYPES: &[OutputTypeDoc] = &[
2729    OutputTypeDoc {
2730        type_name: "Output",
2731        json_paths: &["$"],
2732        summary: "Top-level ScanCode-compatible output object.",
2733        fields: OUTPUT_FIELDS,
2734    },
2735    OutputTypeDoc {
2736        type_name: "OutputHeader",
2737        json_paths: &["$.headers[]"],
2738        summary: "Per-run metadata block for one scan invocation.",
2739        fields: HEADER_FIELDS,
2740    },
2741    OutputTypeDoc {
2742        type_name: "OutputExtraData",
2743        json_paths: &["$.headers[].extra_data"],
2744        summary: "Scanner-owned counts and provenance metadata nested under a header block.",
2745        fields: EXTRA_DATA_FIELDS,
2746    },
2747    OutputTypeDoc {
2748        type_name: "OutputSummary",
2749        json_paths: &["$.summary"],
2750        summary: "Optional codebase-level rollup emitted by summary/classification workflows.",
2751        fields: SUMMARY_FIELDS,
2752    },
2753    OutputTypeDoc {
2754        type_name: "OutputFileInfo",
2755        json_paths: &["$.files[]"],
2756        summary: "File or directory record on the main per-resource output surface.",
2757        fields: FILE_INFO_FIELDS,
2758    },
2759    OutputTypeDoc {
2760        type_name: "OutputPackage",
2761        json_paths: &["$.packages[]"],
2762        summary: "Assembled top-level package record on the public output contract.",
2763        fields: PACKAGE_FIELDS,
2764    },
2765    OutputTypeDoc {
2766        type_name: "OutputPackageData",
2767        json_paths: &["$.files[].package_data[]"],
2768        summary: "Raw parser-emitted package record attached to a specific file.",
2769        fields: PACKAGE_DATA_FIELDS,
2770    },
2771    OutputTypeDoc {
2772        type_name: "OutputDependency",
2773        json_paths: &["$.files[].package_data[].dependencies[]"],
2774        summary: "Raw dependency row preserved on parser-emitted package data.",
2775        fields: DEPENDENCY_FIELDS,
2776    },
2777    OutputTypeDoc {
2778        type_name: "OutputTopLevelDependency",
2779        json_paths: &["$.dependencies[]"],
2780        summary: "Hoisted top-level dependency record emitted after assembly.",
2781        fields: TOP_LEVEL_DEPENDENCY_FIELDS,
2782    },
2783    OutputTypeDoc {
2784        type_name: "OutputTopLevelLicenseDetection",
2785        json_paths: &["$.license_detections[]"],
2786        summary: "Grouped top-level license detection block across the scanned codebase.",
2787        fields: TOP_LEVEL_LICENSE_DETECTION_FIELDS,
2788    },
2789    OutputTypeDoc {
2790        type_name: "OutputTallies",
2791        json_paths: &[
2792            "$.tallies",
2793            "$.tallies_of_key_files",
2794            "$.files[].tallies",
2795            "$.tallies_by_facet[].tallies",
2796        ],
2797        summary: "Tally block used on top-level, key-file, facet, and file-level tally surfaces.",
2798        fields: TALLIES_FIELDS,
2799    },
2800    OutputTypeDoc {
2801        type_name: "OutputFacetTallies",
2802        json_paths: &["$.tallies_by_facet[]"],
2803        summary: "Facet-specific tally wrapper for one user-defined facet label.",
2804        fields: FACET_TALLIES_FIELDS,
2805    },
2806    OutputTypeDoc {
2807        type_name: "OutputTallyEntry",
2808        json_paths: &[
2809            "$.summary.other_license_expressions[]",
2810            "$.summary.other_holders[]",
2811            "$.summary.other_languages[]",
2812            "$.tallies.*[]",
2813        ],
2814        summary: "Single tally bucket entry used throughout summary and tally outputs.",
2815        fields: TALLY_ENTRY_FIELDS,
2816    },
2817    OutputTypeDoc {
2818        type_name: "OutputLicenseClarityScore",
2819        json_paths: &["$.summary.license_clarity_score"],
2820        summary: "Structured license-clarity scoring payload on the summary surface.",
2821        fields: LICENSE_CLARITY_SCORE_FIELDS,
2822    },
2823    OutputTypeDoc {
2824        type_name: "OutputSystemEnvironment",
2825        json_paths: &["$.headers[].extra_data.system_environment"],
2826        summary: "Recorded environment metadata for the scan runtime.",
2827        fields: SYSTEM_ENVIRONMENT_FIELDS,
2828    },
2829    OutputTypeDoc {
2830        type_name: "OutputLicenseIndexProvenance",
2831        json_paths: &["$.headers[].extra_data.license_index_provenance"],
2832        summary: "Provenance block for the effective license index used by the scan.",
2833        fields: LICENSE_INDEX_PROVENANCE_FIELDS,
2834    },
2835    OutputTypeDoc {
2836        type_name: "OutputParty",
2837        json_paths: &[
2838            "$.packages[].parties[]",
2839            "$.files[].package_data[].parties[]",
2840            "$.dependencies[].resolved_package.parties[]",
2841        ],
2842        summary: "Party record used on package and resolved-package surfaces.",
2843        fields: PARTY_FIELDS,
2844    },
2845    OutputTypeDoc {
2846        type_name: "OutputFileReference",
2847        json_paths: &[
2848            "$.files[].package_data[].file_references[]",
2849            "$.dependencies[].resolved_package.file_references[]",
2850        ],
2851        summary: "Referenced-file record used on package-related surfaces.",
2852        fields: FILE_REFERENCE_FIELDS,
2853    },
2854    OutputTypeDoc {
2855        type_name: "OutputLicensePolicyEntry",
2856        json_paths: &["$.files[].license_policy[]"],
2857        summary: "Policy decoration entry attached to file-level license-policy output.",
2858        fields: LICENSE_POLICY_ENTRY_FIELDS,
2859    },
2860    OutputTypeDoc {
2861        type_name: "OutputAuthor",
2862        json_paths: &["$.files[].authors[]"],
2863        summary: "File-level author evidence record.",
2864        fields: AUTHOR_FIELDS,
2865    },
2866    OutputTypeDoc {
2867        type_name: "OutputCopyright",
2868        json_paths: &["$.files[].copyrights[]"],
2869        summary: "File-level copyright evidence record.",
2870        fields: COPYRIGHT_FIELDS,
2871    },
2872    OutputTypeDoc {
2873        type_name: "OutputEmail",
2874        json_paths: &["$.files[].emails[]"],
2875        summary: "File-level email evidence record.",
2876        fields: EMAIL_FIELDS,
2877    },
2878    OutputTypeDoc {
2879        type_name: "OutputHolder",
2880        json_paths: &["$.files[].holders[]"],
2881        summary: "File-level holder evidence record.",
2882        fields: HOLDER_FIELDS,
2883    },
2884    OutputTypeDoc {
2885        type_name: "OutputURL",
2886        json_paths: &["$.files[].urls[]"],
2887        summary: "File-level URL evidence record.",
2888        fields: URL_FIELDS,
2889    },
2890    OutputTypeDoc {
2891        type_name: "OutputLicenseDetection",
2892        json_paths: &[
2893            "$.files[].license_detections[]",
2894            "$.files[].package_data[].license_detections[]",
2895            "$.packages[].license_detections[]",
2896            "$.dependencies[].resolved_package.license_detections[]",
2897        ],
2898        summary: "Grouped license detection record used on file, package_data, package, and resolved-package surfaces.",
2899        fields: LICENSE_DETECTION_FIELDS,
2900    },
2901    OutputTypeDoc {
2902        type_name: "OutputMatch",
2903        json_paths: &[
2904            "$.files[].license_clues[]",
2905            "$.files[].license_detections[].matches[]",
2906            "$.license_detections[].reference_matches[]",
2907        ],
2908        summary: "Match record used for clue output, grouped detections, and top-level representative references.",
2909        fields: MATCH_FIELDS,
2910    },
2911    OutputTypeDoc {
2912        type_name: "OutputLicenseReference",
2913        json_paths: &["$.license_references[]"],
2914        summary: "Top-level license reference record describing one emitted license key and its reference metadata.",
2915        fields: LICENSE_REFERENCE_FIELDS,
2916    },
2917    OutputTypeDoc {
2918        type_name: "OutputLicenseRuleReference",
2919        json_paths: &["$.license_rule_references[]"],
2920        summary: "Top-level license-rule reference record describing one emitted rule and its reference metadata.",
2921        fields: LICENSE_RULE_REFERENCE_FIELDS,
2922    },
2923    OutputTypeDoc {
2924        type_name: "OutputResolvedPackage",
2925        json_paths: &[
2926            "$.dependencies[].resolved_package",
2927            "$.files[].package_data[].dependencies[].resolved_package",
2928        ],
2929        summary: "Resolved package payload nested under dependency rows.",
2930        fields: RESOLVED_PACKAGE_FIELDS,
2931    },
2932    OutputTypeDoc {
2933        type_name: "OutputFileType",
2934        json_paths: &["$.files[].type"],
2935        summary: "Serialized file-type enum used by file records.",
2936        fields: EMPTY_FIELDS,
2937    },
2938    OutputTypeDoc {
2939        type_name: "OutputPackageType",
2940        json_paths: &["$.packages[].type", "$.files[].package_data[].type"],
2941        summary: "Serialized package-type string newtype used by package-related records.",
2942        fields: EMPTY_FIELDS,
2943    },
2944    OutputTypeDoc {
2945        type_name: "OutputDatasourceId",
2946        json_paths: &[
2947            "$.packages[].datasource_ids[]",
2948            "$.dependencies[].datasource_id",
2949            "$.files[].package_data[].datasource_id",
2950        ],
2951        summary: "Serialized datasource-id string newtype used by package and dependency records.",
2952        fields: EMPTY_FIELDS,
2953    },
2954];
2955
2956pub fn documented_output_types() -> &'static [OutputTypeDoc] {
2957    DOCUMENTED_TYPES
2958}
2959
2960#[cfg(test)]
2961mod tests {
2962    use super::documented_output_types;
2963    use std::collections::BTreeSet;
2964
2965    use crate::output_schema::{
2966        OutputAuthor, OutputCopyright, OutputDatasourceId, OutputDependency, OutputEmail,
2967        OutputExtraData, OutputFileInfo, OutputFileReference, OutputFileType, OutputHeader,
2968        OutputHolder, OutputLicenseDetection, OutputLicenseIndexProvenance,
2969        OutputLicensePolicyEntry, OutputMatch, OutputPackage, OutputPackageData, OutputPackageType,
2970        OutputParty, OutputSystemEnvironment, OutputTallies, OutputTallyEntry,
2971        OutputTopLevelDependency, OutputTopLevelLicenseDetection, OutputURL,
2972    };
2973    use serde::Serialize;
2974    use serde_json::{Map, Value};
2975
2976    fn metadata_field_names(type_name: &str) -> BTreeSet<&'static str> {
2977        documented_output_types()
2978            .iter()
2979            .find(|ty| ty.type_name == type_name)
2980            .unwrap_or_else(|| panic!("{} should be documented", type_name))
2981            .fields
2982            .iter()
2983            .map(|field| field.json_name)
2984            .collect()
2985    }
2986
2987    fn serialized_object_keys<T: Serialize>(value: &T) -> BTreeSet<String> {
2988        serde_json::to_value(value)
2989            .expect("serialize")
2990            .as_object()
2991            .expect("object")
2992            .keys()
2993            .cloned()
2994            .collect()
2995    }
2996
2997    fn sample_match() -> OutputMatch {
2998        OutputMatch {
2999            license_expression: "mit".to_string(),
3000            license_expression_spdx: "MIT".to_string(),
3001            from_file: Some("src/lib.rs".to_string()),
3002            start_line: 1,
3003            end_line: 2,
3004            matcher: Some("1-hash".to_string()),
3005            score: 100.0,
3006            matched_length: Some(42),
3007            match_coverage: Some(100.0),
3008            rule_relevance: Some(100),
3009            rule_identifier: Some("mit_1.RULE".to_string()),
3010            rule_url: Some("https://example.invalid/rule".to_string()),
3011            matched_text: Some("Permission is hereby granted".to_string()),
3012            matched_text_diagnostics: Some("diagnostics".to_string()),
3013            referenced_filenames: Some(vec!["LICENSE".to_string()]),
3014        }
3015    }
3016
3017    fn sample_license_detection() -> OutputLicenseDetection {
3018        OutputLicenseDetection {
3019            license_expression: "mit".to_string(),
3020            license_expression_spdx: "MIT".to_string(),
3021            matches: vec![sample_match()],
3022            detection_log: vec!["normalized".to_string()],
3023            identifier: Some("det-1".to_string()),
3024        }
3025    }
3026
3027    fn sample_tally_entry() -> OutputTallyEntry {
3028        OutputTallyEntry {
3029            value: Some("mit".to_string()),
3030            count: 1,
3031        }
3032    }
3033
3034    fn sample_tallies() -> OutputTallies {
3035        OutputTallies {
3036            detected_license_expression: vec![sample_tally_entry()],
3037            copyrights: vec![sample_tally_entry()],
3038            holders: vec![sample_tally_entry()],
3039            authors: vec![sample_tally_entry()],
3040            programming_language: vec![sample_tally_entry()],
3041        }
3042    }
3043
3044    fn sample_party() -> OutputParty {
3045        OutputParty {
3046            r#type: Some("person".to_string()),
3047            role: Some("author".to_string()),
3048            name: Some("Example Person".to_string()),
3049            email: Some("person@example.invalid".to_string()),
3050            url: Some("https://example.invalid/person".to_string()),
3051            organization: Some("Example Org".to_string()),
3052            organization_url: Some("https://example.invalid".to_string()),
3053            timezone: Some("UTC".to_string()),
3054        }
3055    }
3056
3057    fn sample_file_reference() -> OutputFileReference {
3058        OutputFileReference {
3059            path: "LICENSE".to_string(),
3060            size: Some(123),
3061            sha1: Some("a".repeat(40)),
3062            md5: Some("b".repeat(32)),
3063            sha256: Some("c".repeat(64)),
3064            sha512: Some("d".repeat(128)),
3065            extra_data: Some(std::collections::HashMap::from_iter([(
3066                "hint".to_string(),
3067                Value::String("local".to_string()),
3068            )])),
3069        }
3070    }
3071
3072    fn sample_license_policy_entry() -> OutputLicensePolicyEntry {
3073        OutputLicensePolicyEntry {
3074            license_key: "mit".to_string(),
3075            label: "Allowed".to_string(),
3076            color_code: "#00ff00".to_string(),
3077            icon: "check".to_string(),
3078        }
3079    }
3080
3081    fn sample_author() -> OutputAuthor {
3082        OutputAuthor {
3083            author: "Example Author".to_string(),
3084            start_line: 1,
3085            end_line: 1,
3086        }
3087    }
3088
3089    fn sample_copyright() -> OutputCopyright {
3090        OutputCopyright {
3091            copyright: "Copyright 2026 Example".to_string(),
3092            start_line: 1,
3093            end_line: 1,
3094        }
3095    }
3096
3097    fn sample_email() -> OutputEmail {
3098        OutputEmail {
3099            email: "example@example.invalid".to_string(),
3100            start_line: 1,
3101            end_line: 1,
3102        }
3103    }
3104
3105    fn sample_holder() -> OutputHolder {
3106        OutputHolder {
3107            holder: "Example Holder".to_string(),
3108            start_line: 1,
3109            end_line: 1,
3110        }
3111    }
3112
3113    fn sample_url() -> OutputURL {
3114        OutputURL {
3115            url: "https://example.invalid".to_string(),
3116            start_line: 1,
3117            end_line: 1,
3118        }
3119    }
3120
3121    fn sample_package_data() -> OutputPackageData {
3122        OutputPackageData {
3123            package_type: Some(OutputPackageType::from(crate::models::PackageType::Cargo)),
3124            namespace: Some("example".to_string()),
3125            name: Some("crate-name".to_string()),
3126            version: Some("1.2.3".to_string()),
3127            qualifiers: Some(std::collections::HashMap::from_iter([(
3128                "arch".to_string(),
3129                "x86_64".to_string(),
3130            )])),
3131            subpath: Some("sub".to_string()),
3132            primary_language: Some("Rust".to_string()),
3133            description: Some("Example package data".to_string()),
3134            release_date: Some("2026-05-31".to_string()),
3135            parties: vec![sample_party()],
3136            keywords: vec!["example".to_string()],
3137            homepage_url: Some("https://example.invalid/home".to_string()),
3138            download_url: Some("https://example.invalid/download".to_string()),
3139            size: Some(42),
3140            sha1: Some("a".repeat(40)),
3141            md5: Some("b".repeat(32)),
3142            sha256: Some("c".repeat(64)),
3143            sha512: Some("d".repeat(128)),
3144            bug_tracking_url: Some("https://example.invalid/issues".to_string()),
3145            code_view_url: Some("https://example.invalid/code".to_string()),
3146            vcs_url: Some("git+https://example.invalid/repo.git".to_string()),
3147            copyright: Some("Copyright 2026 Example".to_string()),
3148            holder: Some("Example Holder".to_string()),
3149            declared_license_expression: Some("mit".to_string()),
3150            declared_license_expression_spdx: Some("MIT".to_string()),
3151            license_detections: vec![sample_license_detection()],
3152            other_license_expression: Some("apache-2.0".to_string()),
3153            other_license_expression_spdx: Some("Apache-2.0".to_string()),
3154            other_license_detections: vec![sample_license_detection()],
3155            extracted_license_statement: Some("MIT".to_string()),
3156            notice_text: Some("notice".to_string()),
3157            source_packages: vec!["pkg:cargo/source@1.0.0".to_string()],
3158            file_references: vec![sample_file_reference()],
3159            is_private: true,
3160            is_virtual: true,
3161            extra_data: Some(std::collections::HashMap::from_iter([(
3162                "custom".to_string(),
3163                Value::String("value".to_string()),
3164            )])),
3165            dependencies: vec![sample_dependency()],
3166            repository_homepage_url: Some("https://example.invalid/repo-home".to_string()),
3167            repository_download_url: Some("https://example.invalid/repo-download".to_string()),
3168            api_data_url: Some("https://example.invalid/api".to_string()),
3169            datasource_id: Some(OutputDatasourceId::from(
3170                crate::models::DatasourceId::CargoToml,
3171            )),
3172            purl: Some("pkg:cargo/example/crate-name@1.2.3".to_string()),
3173        }
3174    }
3175
3176    fn sample_dependency() -> OutputDependency {
3177        OutputDependency {
3178            purl: Some("pkg:cargo/example/dep@1.0.0".to_string()),
3179            extracted_requirement: Some("^1.0".to_string()),
3180            scope: Some("runtime".to_string()),
3181            is_runtime: Some(true),
3182            is_optional: Some(false),
3183            is_pinned: Some(true),
3184            is_direct: Some(true),
3185            resolved_package: None,
3186            extra_data: Some(std::collections::HashMap::from_iter([(
3187                "kind".to_string(),
3188                Value::String("normal".to_string()),
3189            )])),
3190        }
3191    }
3192
3193    fn sample_top_level_dependency() -> OutputTopLevelDependency {
3194        OutputTopLevelDependency {
3195            purl: Some("pkg:cargo/example/dep@1.0.0".to_string()),
3196            extracted_requirement: Some("^1.0".to_string()),
3197            scope: Some("runtime".to_string()),
3198            is_runtime: Some(true),
3199            is_optional: Some(false),
3200            is_pinned: Some(true),
3201            is_direct: Some(true),
3202            resolved_package: None,
3203            extra_data: Some(std::collections::HashMap::from_iter([(
3204                "kind".to_string(),
3205                Value::String("normal".to_string()),
3206            )])),
3207            dependency_uid: "dep-uid".to_string(),
3208            for_package_uid: Some("pkg-uid".to_string()),
3209            datafile_path: "Cargo.toml".to_string(),
3210            datasource_id: OutputDatasourceId::from(crate::models::DatasourceId::CargoToml),
3211            namespace: Some("example".to_string()),
3212        }
3213    }
3214
3215    fn sample_top_level_license_detection() -> OutputTopLevelLicenseDetection {
3216        OutputTopLevelLicenseDetection {
3217            identifier: "top-1".to_string(),
3218            license_expression: "mit".to_string(),
3219            license_expression_spdx: "MIT".to_string(),
3220            detection_count: 1,
3221            detection_log: vec!["grouped".to_string()],
3222            reference_matches: vec![sample_match()],
3223        }
3224    }
3225
3226    fn sample_header() -> OutputHeader {
3227        OutputHeader {
3228            tool_name: "provenant".to_string(),
3229            tool_version: "0.1.7".to_string(),
3230            options: Map::from_iter([("--license".to_string(), Value::Bool(true))]),
3231            notice: "Generated with Provenant".to_string(),
3232            start_timestamp: "2026-05-31T00:00:00Z".to_string(),
3233            end_timestamp: "2026-05-31T00:00:10Z".to_string(),
3234            output_format_version: "3.0.0".to_string(),
3235            duration: 10.0,
3236            errors: vec!["none".to_string()],
3237            warnings: vec!["warning".to_string()],
3238            extra_data: OutputExtraData {
3239                system_environment: OutputSystemEnvironment {
3240                    operating_system: "Linux".to_string(),
3241                    cpu_architecture: "x86_64".to_string(),
3242                    platform: "linux".to_string(),
3243                    platform_version: "6.0".to_string(),
3244                    rust_version: "1.88.0".to_string(),
3245                },
3246                spdx_license_list_version: "3.26".to_string(),
3247                files_count: 1,
3248                directories_count: 1,
3249                excluded_count: 0,
3250                license_index_provenance: Some(OutputLicenseIndexProvenance {
3251                    source: "embedded".to_string(),
3252                    dataset_fingerprint: "fingerprint".to_string(),
3253                    ignored_rules: vec!["rule-a".to_string()],
3254                    ignored_licenses: vec!["lic-a".to_string()],
3255                    ignored_rules_due_to_licenses: vec!["rule-b".to_string()],
3256                    added_rules: vec!["rule-c".to_string()],
3257                    replaced_rules: vec!["rule-d".to_string()],
3258                    added_licenses: vec!["lic-b".to_string()],
3259                    replaced_licenses: vec!["lic-c".to_string()],
3260                }),
3261            },
3262        }
3263    }
3264
3265    fn sample_file_info() -> OutputFileInfo {
3266        OutputFileInfo {
3267            name: "mod.rs".to_string(),
3268            base_name: "mod".to_string(),
3269            extension: ".rs".to_string(),
3270            path: "src/mod.rs".to_string(),
3271            file_type: OutputFileType::File,
3272            mime_type: Some("text/rust".to_string()),
3273            file_type_label: Some("source".to_string()),
3274            size: 123,
3275            date: Some("2026-05-31".to_string()),
3276            sha1: Some("a".repeat(40)),
3277            md5: Some("b".repeat(32)),
3278            sha256: Some("c".repeat(64)),
3279            sha1_git: Some("d".repeat(40)),
3280            programming_language: Some("Rust".to_string()),
3281            package_data: vec![sample_package_data()],
3282            license_expression: Some("MIT".to_string()),
3283            license_detections: vec![sample_license_detection()],
3284            license_clues: vec![sample_match()],
3285            percentage_of_license_text: Some(50.0),
3286            copyrights: vec![sample_copyright()],
3287            holders: vec![sample_holder()],
3288            authors: vec![sample_author()],
3289            emails: vec![sample_email()],
3290            urls: vec![sample_url()],
3291            for_packages: vec!["pkg-uid".to_string()],
3292            scan_errors: vec!["parse warning".to_string()],
3293            license_policy: Some(vec![sample_license_policy_entry()]),
3294            is_generated: Some(true),
3295            is_binary: Some(false),
3296            is_text: Some(true),
3297            is_archive: Some(false),
3298            is_media: Some(false),
3299            is_source: Some(true),
3300            is_script: Some(false),
3301            files_count: Some(1),
3302            dirs_count: Some(0),
3303            size_count: Some(123),
3304            source_count: Some(1),
3305            is_legal: true,
3306            is_manifest: true,
3307            is_readme: true,
3308            is_top_level: true,
3309            is_key_file: true,
3310            is_referenced: true,
3311            is_community: true,
3312            facets: vec!["core".to_string()],
3313            tallies: Some(sample_tallies()),
3314        }
3315    }
3316
3317    fn sample_package() -> OutputPackage {
3318        OutputPackage {
3319            package_type: Some(OutputPackageType::from(crate::models::PackageType::Cargo)),
3320            namespace: Some("example".to_string()),
3321            name: Some("crate-name".to_string()),
3322            version: Some("1.2.3".to_string()),
3323            qualifiers: Some(std::collections::HashMap::from_iter([(
3324                "arch".to_string(),
3325                "x86_64".to_string(),
3326            )])),
3327            subpath: Some("sub".to_string()),
3328            primary_language: Some("Rust".to_string()),
3329            description: Some("Example package".to_string()),
3330            release_date: Some("2026-05-31".to_string()),
3331            parties: vec![sample_party()],
3332            keywords: vec!["example".to_string()],
3333            homepage_url: Some("https://example.invalid/home".to_string()),
3334            download_url: Some("https://example.invalid/download".to_string()),
3335            size: Some(42),
3336            sha1: Some("a".repeat(40)),
3337            md5: Some("b".repeat(32)),
3338            sha256: Some("c".repeat(64)),
3339            sha512: Some("d".repeat(128)),
3340            bug_tracking_url: Some("https://example.invalid/issues".to_string()),
3341            code_view_url: Some("https://example.invalid/code".to_string()),
3342            vcs_url: Some("git+https://example.invalid/repo.git".to_string()),
3343            copyright: Some("Copyright 2026 Example".to_string()),
3344            holder: Some("Example Holder".to_string()),
3345            declared_license_expression: Some("mit".to_string()),
3346            declared_license_expression_spdx: Some("MIT".to_string()),
3347            license_detections: vec![sample_license_detection()],
3348            other_license_expression: Some("apache-2.0".to_string()),
3349            other_license_expression_spdx: Some("Apache-2.0".to_string()),
3350            other_license_detections: vec![sample_license_detection()],
3351            extracted_license_statement: Some("MIT".to_string()),
3352            notice_text: Some("notice".to_string()),
3353            source_packages: vec!["pkg:cargo/source@1.0.0".to_string()],
3354            is_private: true,
3355            is_virtual: true,
3356            extra_data: Some(std::collections::HashMap::from_iter([(
3357                "custom".to_string(),
3358                Value::String("value".to_string()),
3359            )])),
3360            repository_homepage_url: Some("https://example.invalid/repo-home".to_string()),
3361            repository_download_url: Some("https://example.invalid/repo-download".to_string()),
3362            api_data_url: Some("https://example.invalid/api".to_string()),
3363            purl: Some("pkg:cargo/example/crate-name@1.2.3".to_string()),
3364            package_uid: "pkg-uid".to_string(),
3365            datafile_paths: vec!["Cargo.toml".to_string()],
3366            datasource_ids: vec![OutputDatasourceId::from(
3367                crate::models::DatasourceId::CargoToml,
3368            )],
3369        }
3370    }
3371
3372    fn assert_metadata_matches_serialized_keys<T: Serialize>(type_name: &str, value: &T) {
3373        let documented = metadata_field_names(type_name);
3374        let serialized = serialized_object_keys(value)
3375            .into_iter()
3376            .collect::<BTreeSet<_>>();
3377        let documented_owned = documented
3378            .iter()
3379            .map(|s| s.to_string())
3380            .collect::<BTreeSet<_>>();
3381        assert_eq!(
3382            documented_owned, serialized,
3383            "metadata mismatch for {}",
3384            type_name
3385        );
3386    }
3387
3388    #[test]
3389    fn documented_type_names_are_unique() {
3390        let mut seen = BTreeSet::new();
3391        for ty in documented_output_types() {
3392            assert!(
3393                seen.insert(ty.type_name),
3394                "duplicate type doc: {}",
3395                ty.type_name
3396            );
3397        }
3398    }
3399
3400    #[test]
3401    fn documented_json_paths_are_unique() {
3402        let mut seen = BTreeSet::new();
3403        for ty in documented_output_types() {
3404            for path in ty.json_paths {
3405                assert!(seen.insert(*path), "duplicate json path doc: {}", path);
3406            }
3407        }
3408    }
3409
3410    #[test]
3411    fn documented_field_names_are_unique_per_type() {
3412        for ty in documented_output_types() {
3413            let mut seen = BTreeSet::new();
3414            for field in ty.fields {
3415                assert!(
3416                    seen.insert(field.json_name),
3417                    "duplicate field doc in {}: {}",
3418                    ty.type_name,
3419                    field.json_name
3420                );
3421            }
3422        }
3423    }
3424
3425    #[test]
3426    fn output_file_info_doc_starts_with_public_serialization_order() {
3427        let file_info = documented_output_types()
3428            .iter()
3429            .find(|ty| ty.type_name == "OutputFileInfo")
3430            .expect("OutputFileInfo should be documented");
3431        let fields = file_info
3432            .fields
3433            .iter()
3434            .map(|field| field.json_name)
3435            .collect::<Vec<_>>();
3436
3437        assert_eq!(
3438            &fields[..5],
3439            &["path", "type", "name", "base_name", "extension",]
3440        );
3441    }
3442
3443    #[test]
3444    fn metadata_matches_serialized_keys_for_core_documented_types() {
3445        assert_metadata_matches_serialized_keys("OutputHeader", &sample_header());
3446        assert_metadata_matches_serialized_keys("OutputFileInfo", &sample_file_info());
3447        assert_metadata_matches_serialized_keys("OutputPackage", &sample_package());
3448        assert_metadata_matches_serialized_keys("OutputPackageData", &sample_package_data());
3449        assert_metadata_matches_serialized_keys("OutputDependency", &sample_dependency());
3450        assert_metadata_matches_serialized_keys(
3451            "OutputTopLevelDependency",
3452            &sample_top_level_dependency(),
3453        );
3454        assert_metadata_matches_serialized_keys(
3455            "OutputTopLevelLicenseDetection",
3456            &sample_top_level_license_detection(),
3457        );
3458    }
3459}