fallow 2.90.0 → 2.92.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +10 -10
- package/schema.json +122 -2
- package/skills/fallow/SKILL.md +15 -11
- package/skills/fallow/references/cli-reference.md +166 -70
- package/skills/fallow/references/gotchas.md +1 -1
- package/skills/fallow/references/patterns.md +14 -1
- package/types/output-contract.d.ts +592 -82
|
@@ -71,7 +71,7 @@ kind: "dupes"
|
|
|
71
71
|
kind: "dead-code-grouped"
|
|
72
72
|
}) | (ImpactReport & {
|
|
73
73
|
kind: "impact"
|
|
74
|
-
}) | (SecurityOutput & {
|
|
74
|
+
}) | ((SecurityOutput | SecuritySummaryOutput) & {
|
|
75
75
|
kind: "security"
|
|
76
76
|
}) | (CheckOutput & {
|
|
77
77
|
kind: "dead-code"
|
|
@@ -170,7 +170,7 @@ export type IssueAction = (FixAction | SuppressLineAction | SuppressFileAction |
|
|
|
170
170
|
* Discriminant string for [`FixAction`]. Kebab-case per the JSON output
|
|
171
171
|
* contract.
|
|
172
172
|
*/
|
|
173
|
-
export type FixActionType = ("remove-export" | "delete-file" | "remove-dependency" | "move-dependency" | "remove-enum-member" | "remove-class-member" | "resolve-import" | "install-dependency" | "remove-duplicate" | "move-to-dev" | "refactor-cycle" | "refactor-re-export-cycle" | "refactor-boundary" | "export-type" | "remove-catalog-entry" | "remove-empty-catalog-group" | "update-catalog-reference" | "add-catalog-entry" | "remove-catalog-reference" | "remove-dependency-override" | "fix-dependency-override")
|
|
173
|
+
export type FixActionType = ("remove-export" | "delete-file" | "remove-dependency" | "move-dependency" | "remove-enum-member" | "remove-class-member" | "resolve-import" | "install-dependency" | "remove-duplicate" | "move-to-dev" | "refactor-cycle" | "refactor-re-export-cycle" | "refactor-boundary" | "export-type" | "remove-catalog-entry" | "remove-empty-catalog-group" | "update-catalog-reference" | "add-catalog-entry" | "remove-catalog-reference" | "remove-dependency-override" | "fix-dependency-override" | "resolve-policy-violation")
|
|
174
174
|
/**
|
|
175
175
|
* Singleton discriminant for [`SuppressLineAction`].
|
|
176
176
|
*/
|
|
@@ -232,6 +232,17 @@ export type MemberKind = ("enum_member" | "class_method" | "class_property" | "n
|
|
|
232
232
|
* Discriminator for [`ReExportCycle`]: which structural shape was detected.
|
|
233
233
|
*/
|
|
234
234
|
export type ReExportCycleKind = ("multi-node" | "self-loop")
|
|
235
|
+
/**
|
|
236
|
+
* Which rule-pack rule kind produced a [`PolicyViolation`].
|
|
237
|
+
*/
|
|
238
|
+
export type PolicyRuleKind = ("banned-call" | "banned-import")
|
|
239
|
+
/**
|
|
240
|
+
* Effective severity of a single [`PolicyViolation`]. Per-rule `severity`
|
|
241
|
+
* overrides the `rules."policy-violation"` master; `off` rules emit nothing,
|
|
242
|
+
* so only `error` and `warn` appear on the wire. The exit-code gate inspects
|
|
243
|
+
* this per-finding value, not the master severity.
|
|
244
|
+
*/
|
|
245
|
+
export type PolicyViolationSeverity = ("error" | "warn")
|
|
235
246
|
/**
|
|
236
247
|
* The origin of a stale suppression: inline comment or JSDoc tag.
|
|
237
248
|
*/
|
|
@@ -322,6 +333,18 @@ error: string
|
|
|
322
333
|
kind: "malformed-tsconfig"
|
|
323
334
|
} | {
|
|
324
335
|
kind: "tsconfig-reference-dir-missing"
|
|
336
|
+
} | {
|
|
337
|
+
/**
|
|
338
|
+
* On-disk size of the skipped file in bytes.
|
|
339
|
+
*/
|
|
340
|
+
size_bytes: number
|
|
341
|
+
kind: "skipped-large-file"
|
|
342
|
+
} | {
|
|
343
|
+
/**
|
|
344
|
+
* On-disk size of the skipped file in bytes.
|
|
345
|
+
*/
|
|
346
|
+
size_bytes: number
|
|
347
|
+
kind: "skipped-minified-file"
|
|
325
348
|
})
|
|
326
349
|
/**
|
|
327
350
|
* Discriminant for [`CloneGroupAction::kind`]. Mirrors the action types
|
|
@@ -600,12 +623,18 @@ export type ImpactTrendDirection = ("improving" | "declining" | "stable")
|
|
|
600
623
|
* The `fallow security --format json` schema version. Independently versioned
|
|
601
624
|
* from the main contract, mirroring `ImpactReportSchemaVersion`.
|
|
602
625
|
*/
|
|
603
|
-
export type SecuritySchemaVersion = "1"
|
|
626
|
+
export type SecuritySchemaVersion = ("1" | "2" | "3" | "4" | "5" | "6")
|
|
627
|
+
/**
|
|
628
|
+
* Severity level for rules.
|
|
629
|
+
*
|
|
630
|
+
* Controls whether an issue type causes CI failure (`error`), is reported
|
|
631
|
+
* without failing (`warn`), or is suppressed entirely (`off`).
|
|
632
|
+
*/
|
|
633
|
+
export type Severity = ("error" | "warn" | "off")
|
|
604
634
|
/**
|
|
605
|
-
* Gate mode for `fallow security --gate <mode
|
|
606
|
-
* the value `newly-reachable`.
|
|
635
|
+
* Gate mode for `fallow security --gate <mode>`.
|
|
607
636
|
*/
|
|
608
|
-
export type SecurityGateMode = "new"
|
|
637
|
+
export type SecurityGateMode = ("new" | "newly-reachable")
|
|
609
638
|
/**
|
|
610
639
|
* Gate verdict on the wire. `fail` is the CI-state token; human output renders
|
|
611
640
|
* it as "REVIEW REQUIRED" because these stay unverified candidates, never
|
|
@@ -617,14 +646,32 @@ export type SecurityGateVerdict = ("pass" | "fail")
|
|
|
617
646
|
* verification, NOT verified vulnerabilities.
|
|
618
647
|
*/
|
|
619
648
|
export type SecurityFindingKind = ("client-server-leak" | "tainted-sink")
|
|
649
|
+
/**
|
|
650
|
+
* Verification-priority tier for a security candidate. This is ranking, not an
|
|
651
|
+
* exploitability verdict.
|
|
652
|
+
*/
|
|
653
|
+
export type SecuritySeverity = ("high" | "medium" | "low")
|
|
620
654
|
/**
|
|
621
655
|
* The role a hop plays in a security finding's structural import trace.
|
|
622
656
|
*/
|
|
623
|
-
export type TraceHopRole = ("client-boundary" | "untrusted-source" | "intermediate" | "secret-source" | "sink")
|
|
657
|
+
export type TraceHopRole = ("client-boundary" | "untrusted-source" | "module-source" | "intermediate" | "secret-source" | "sink")
|
|
624
658
|
/**
|
|
625
659
|
* Dead-code issue kind linked to a security candidate.
|
|
626
660
|
*/
|
|
627
661
|
export type SecurityDeadCodeKind = ("unused-file" | "unused-export")
|
|
662
|
+
/**
|
|
663
|
+
* How strongly the untrusted-source signal is associated with the sink, a
|
|
664
|
+
* structured discriminator so a consumer can tier candidates without parsing
|
|
665
|
+
* the human `evidence` prose. Present only when
|
|
666
|
+
* [`SecurityReachability::reachable_from_untrusted_source`] is true. Neither
|
|
667
|
+
* value proves exploitability; both are ranking signals (issue #885 doctrine:
|
|
668
|
+
* rank, never gate).
|
|
669
|
+
*/
|
|
670
|
+
export type TaintConfidence = ("arg-level" | "module-level")
|
|
671
|
+
/**
|
|
672
|
+
* Static URL construction shape captured for URL-shaped security sinks.
|
|
673
|
+
*/
|
|
674
|
+
export type SecurityUrlShape = ("fixed-origin-dynamic-path" | "dynamic-origin")
|
|
628
675
|
/**
|
|
629
676
|
* Runtime coverage state for the function enclosing a security sink.
|
|
630
677
|
* This is production-observation evidence, not an exploitability verdict.
|
|
@@ -634,6 +681,15 @@ export type SecurityRuntimeState = ("runtime-hot" | "runtime-cold" | "never-exec
|
|
|
634
681
|
* Defensive control family detected on a source to sink path.
|
|
635
682
|
*/
|
|
636
683
|
export type SecurityControlKind = ("sanitization" | "validation" | "authentication" | "authorization")
|
|
684
|
+
/**
|
|
685
|
+
* Why a sink-shaped callee could not be flattened into a static catalogue
|
|
686
|
+
* path.
|
|
687
|
+
*/
|
|
688
|
+
export type SkippedSecurityCalleeReason = ("computed-member" | "dynamic-dispatch" | "unsupported-assignment-object")
|
|
689
|
+
/**
|
|
690
|
+
* Syntactic expression shape for a skipped security callee.
|
|
691
|
+
*/
|
|
692
|
+
export type SkippedSecurityCalleeExpressionKind = ("static-member-expression" | "computed-member-expression" | "identifier" | "other")
|
|
637
693
|
/**
|
|
638
694
|
* Discriminator value for [`CodeClimateIssue::kind`].
|
|
639
695
|
*/
|
|
@@ -659,11 +715,20 @@ command: AuditCommand
|
|
|
659
715
|
verdict: AuditVerdict
|
|
660
716
|
changed_files_count: number
|
|
661
717
|
base_ref: string
|
|
718
|
+
/**
|
|
719
|
+
* Human-readable provenance of `base_ref`, e.g. `merge-base with
|
|
720
|
+
* origin/main`, `local main`, or `FALLOW_AUDIT_BASE=upstream/main`.
|
|
721
|
+
* Present when the base was auto-detected or set via `FALLOW_AUDIT_BASE`;
|
|
722
|
+
* absent for an explicit `--base` (the ref the user typed is already
|
|
723
|
+
* self-describing).
|
|
724
|
+
*/
|
|
725
|
+
base_description?: (string | null)
|
|
662
726
|
head_sha?: (string | null)
|
|
663
727
|
elapsed_ms: ElapsedMs
|
|
664
728
|
base_snapshot_skipped?: (boolean | null)
|
|
665
729
|
summary: AuditSummary
|
|
666
730
|
attribution: AuditAttribution
|
|
731
|
+
_meta?: (Meta | null)
|
|
667
732
|
dead_code?: (CheckOutput | null)
|
|
668
733
|
duplication?: (DupesReportPayload | null)
|
|
669
734
|
complexity?: (HealthReport | null)
|
|
@@ -690,6 +755,88 @@ complexity_inherited: number
|
|
|
690
755
|
duplication_introduced: number
|
|
691
756
|
duplication_inherited: number
|
|
692
757
|
}
|
|
758
|
+
/**
|
|
759
|
+
* Metric and rule definitions emitted under `_meta` when `--explain` is
|
|
760
|
+
* passed (always present in MCP responses). Helps AI agents and CI systems
|
|
761
|
+
* interpret metric values without re-reading the docs site.
|
|
762
|
+
*/
|
|
763
|
+
export interface Meta {
|
|
764
|
+
/**
|
|
765
|
+
* URL to the documentation page for this command.
|
|
766
|
+
*/
|
|
767
|
+
docs?: (string | null)
|
|
768
|
+
/**
|
|
769
|
+
* Local telemetry correlation metadata for agent follow-up runs.
|
|
770
|
+
*/
|
|
771
|
+
telemetry?: (TelemetryMeta | null)
|
|
772
|
+
/**
|
|
773
|
+
* Per-field definitions for envelope fields and action payload fields.
|
|
774
|
+
*/
|
|
775
|
+
field_definitions?: {
|
|
776
|
+
[k: string]: string
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Per-metric definitions: name, description, range, interpretation.
|
|
780
|
+
*/
|
|
781
|
+
metrics?: {
|
|
782
|
+
[k: string]: MetaMetric
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Per-rule definitions for check command output.
|
|
786
|
+
*/
|
|
787
|
+
rules?: {
|
|
788
|
+
[k: string]: MetaRule
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Privacy-safe local run metadata emitted for JSON consumers.
|
|
793
|
+
*/
|
|
794
|
+
export interface TelemetryMeta {
|
|
795
|
+
/**
|
|
796
|
+
* Ephemeral local token that may be passed to the hidden `--parent-run`
|
|
797
|
+
* flag on a later command. It is not derived from repository, path, user,
|
|
798
|
+
* machine, project, or cloud data.
|
|
799
|
+
*/
|
|
800
|
+
analysis_run_id?: (string | null)
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Single-metric definition inside [`Meta::metrics`].
|
|
804
|
+
*/
|
|
805
|
+
export interface MetaMetric {
|
|
806
|
+
/**
|
|
807
|
+
* Human-readable metric name.
|
|
808
|
+
*/
|
|
809
|
+
name?: (string | null)
|
|
810
|
+
/**
|
|
811
|
+
* What this metric measures and how it is computed.
|
|
812
|
+
*/
|
|
813
|
+
description?: (string | null)
|
|
814
|
+
/**
|
|
815
|
+
* Valid value range (e.g., `"[0, 100]"`).
|
|
816
|
+
*/
|
|
817
|
+
range?: (string | null)
|
|
818
|
+
/**
|
|
819
|
+
* How to read the value (e.g., `"lower is better"`).
|
|
820
|
+
*/
|
|
821
|
+
interpretation?: (string | null)
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Single-rule definition inside [`Meta::rules`].
|
|
825
|
+
*/
|
|
826
|
+
export interface MetaRule {
|
|
827
|
+
/**
|
|
828
|
+
* Human-readable rule name.
|
|
829
|
+
*/
|
|
830
|
+
name?: (string | null)
|
|
831
|
+
/**
|
|
832
|
+
* What this rule detects.
|
|
833
|
+
*/
|
|
834
|
+
description?: (string | null)
|
|
835
|
+
/**
|
|
836
|
+
* URL to the rule documentation.
|
|
837
|
+
*/
|
|
838
|
+
docs?: (string | null)
|
|
839
|
+
}
|
|
693
840
|
/**
|
|
694
841
|
* Envelope emitted by `fallow dead-code --format json` (plus the `check`
|
|
695
842
|
* block inside the combined and audit envelopes).
|
|
@@ -817,6 +964,25 @@ re_export_cycles?: ReExportCycleFinding[]
|
|
|
817
964
|
* array natively.
|
|
818
965
|
*/
|
|
819
966
|
boundary_violations?: BoundaryViolationFinding[]
|
|
967
|
+
/**
|
|
968
|
+
* Files that matched no architecture boundary zone while
|
|
969
|
+
* `boundaries.coverage.requireAllFiles` was enabled.
|
|
970
|
+
*/
|
|
971
|
+
boundary_coverage_violations?: BoundaryCoverageViolationFinding[]
|
|
972
|
+
/**
|
|
973
|
+
* Calls from zoned files to callees forbidden for that zone via
|
|
974
|
+
* `boundaries.calls.forbidden`. Wrapped in
|
|
975
|
+
* [`BoundaryCallViolationFinding`] so each entry carries a typed
|
|
976
|
+
* `actions` array natively.
|
|
977
|
+
*/
|
|
978
|
+
boundary_call_violations?: BoundaryCallViolationFinding[]
|
|
979
|
+
/**
|
|
980
|
+
* Banned calls and banned imports matched by declarative rule packs
|
|
981
|
+
* (`rulePacks` config). Wrapped in [`PolicyViolationFinding`] so each
|
|
982
|
+
* entry carries a typed `actions` array natively. Each finding carries
|
|
983
|
+
* its effective per-rule severity.
|
|
984
|
+
*/
|
|
985
|
+
policy_violations?: PolicyViolationFinding[]
|
|
820
986
|
/**
|
|
821
987
|
* Suppression comments or JSDoc tags that no longer match any issue.
|
|
822
988
|
*/
|
|
@@ -959,6 +1125,18 @@ re_export_cycles?: number
|
|
|
959
1125
|
* Imports that cross architecture boundary rules.
|
|
960
1126
|
*/
|
|
961
1127
|
boundary_violations: number
|
|
1128
|
+
/**
|
|
1129
|
+
* Files that match no architecture boundary zone.
|
|
1130
|
+
*/
|
|
1131
|
+
boundary_coverage_violations?: number
|
|
1132
|
+
/**
|
|
1133
|
+
* Calls from zoned files to callees forbidden for that zone.
|
|
1134
|
+
*/
|
|
1135
|
+
boundary_call_violations?: number
|
|
1136
|
+
/**
|
|
1137
|
+
* Banned calls and banned imports matched by declarative rule packs.
|
|
1138
|
+
*/
|
|
1139
|
+
policy_violations?: number
|
|
962
1140
|
/**
|
|
963
1141
|
* Suppression comments that no longer match a finding.
|
|
964
1142
|
*/
|
|
@@ -1646,7 +1824,7 @@ introduced?: (AuditIntroduced | null)
|
|
|
1646
1824
|
*/
|
|
1647
1825
|
export interface TestOnlyDependencyFinding {
|
|
1648
1826
|
/**
|
|
1649
|
-
* Production dependency that is only imported by test files
|
|
1827
|
+
* Production dependency that is only imported by test files , consider
|
|
1650
1828
|
* moving to devDependencies.
|
|
1651
1829
|
*/
|
|
1652
1830
|
package_name: string
|
|
@@ -1817,6 +1995,124 @@ actions: IssueAction[]
|
|
|
1817
1995
|
*/
|
|
1818
1996
|
introduced?: (AuditIntroduced | null)
|
|
1819
1997
|
}
|
|
1998
|
+
/**
|
|
1999
|
+
* Wire-shape envelope for a [`BoundaryCoverageViolation`] finding. Carries
|
|
2000
|
+
* actions for assigning the file to a zone or explicitly allowing it to stay
|
|
2001
|
+
* unmatched.
|
|
2002
|
+
*/
|
|
2003
|
+
export interface BoundaryCoverageViolationFinding {
|
|
2004
|
+
/**
|
|
2005
|
+
* The unmatched source file.
|
|
2006
|
+
*/
|
|
2007
|
+
path: string
|
|
2008
|
+
/**
|
|
2009
|
+
* 1-based line number used for diagnostics.
|
|
2010
|
+
*/
|
|
2011
|
+
line: number
|
|
2012
|
+
/**
|
|
2013
|
+
* 0-based byte column offset used for diagnostics.
|
|
2014
|
+
*/
|
|
2015
|
+
col: number
|
|
2016
|
+
/**
|
|
2017
|
+
* Suggested next steps.
|
|
2018
|
+
*/
|
|
2019
|
+
actions: IssueAction[]
|
|
2020
|
+
/**
|
|
2021
|
+
* Set by the audit pass when this finding is introduced relative to
|
|
2022
|
+
* the merge-base.
|
|
2023
|
+
*/
|
|
2024
|
+
introduced?: (AuditIntroduced | null)
|
|
2025
|
+
}
|
|
2026
|
+
/**
|
|
2027
|
+
* Wire-shape envelope for a [`BoundaryCallViolation`] finding. Carries
|
|
2028
|
+
* actions for refactoring the forbidden call out of the zone or suppressing
|
|
2029
|
+
* it with the shared `boundary-violation` token.
|
|
2030
|
+
*/
|
|
2031
|
+
export interface BoundaryCallViolationFinding {
|
|
2032
|
+
/**
|
|
2033
|
+
* The zoned source file making the forbidden call.
|
|
2034
|
+
*/
|
|
2035
|
+
path: string
|
|
2036
|
+
/**
|
|
2037
|
+
* 1-based line number of the call site.
|
|
2038
|
+
*/
|
|
2039
|
+
line: number
|
|
2040
|
+
/**
|
|
2041
|
+
* 0-based byte column offset of the call site.
|
|
2042
|
+
*/
|
|
2043
|
+
col: number
|
|
2044
|
+
/**
|
|
2045
|
+
* The zone the calling file is classified into.
|
|
2046
|
+
*/
|
|
2047
|
+
zone: string
|
|
2048
|
+
/**
|
|
2049
|
+
* The callee path as written at the call site (e.g. `cp.exec`).
|
|
2050
|
+
*/
|
|
2051
|
+
callee: string
|
|
2052
|
+
/**
|
|
2053
|
+
* The configured pattern that matched (e.g. `child_process.*`), so
|
|
2054
|
+
* consumers can see both the written path and the rule that fired.
|
|
2055
|
+
*/
|
|
2056
|
+
pattern: string
|
|
2057
|
+
/**
|
|
2058
|
+
* Suggested next steps.
|
|
2059
|
+
*/
|
|
2060
|
+
actions: IssueAction[]
|
|
2061
|
+
/**
|
|
2062
|
+
* Set by the audit pass when this finding is introduced relative to
|
|
2063
|
+
* the merge-base.
|
|
2064
|
+
*/
|
|
2065
|
+
introduced?: (AuditIntroduced | null)
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* Wire-shape envelope for a [`PolicyViolation`] finding. Carries actions for
|
|
2069
|
+
* replacing the banned call or import, or suppressing it with the
|
|
2070
|
+
* `policy-violation` token.
|
|
2071
|
+
*/
|
|
2072
|
+
export interface PolicyViolationFinding {
|
|
2073
|
+
/**
|
|
2074
|
+
* The source file containing the banned call or import.
|
|
2075
|
+
*/
|
|
2076
|
+
path: string
|
|
2077
|
+
/**
|
|
2078
|
+
* 1-based line number of the call site or import declaration.
|
|
2079
|
+
*/
|
|
2080
|
+
line: number
|
|
2081
|
+
/**
|
|
2082
|
+
* 0-based byte column offset of the call site or import declaration.
|
|
2083
|
+
*/
|
|
2084
|
+
col: number
|
|
2085
|
+
/**
|
|
2086
|
+
* Name of the rule pack that declared the matching rule.
|
|
2087
|
+
*/
|
|
2088
|
+
pack: string
|
|
2089
|
+
/**
|
|
2090
|
+
* Id of the matching rule inside the pack. `pack` plus `rule_id` is the
|
|
2091
|
+
* finding's policy identity.
|
|
2092
|
+
*/
|
|
2093
|
+
rule_id: string
|
|
2094
|
+
kind: PolicyRuleKind
|
|
2095
|
+
/**
|
|
2096
|
+
* What matched: the written callee path for `banned-call` (e.g.
|
|
2097
|
+
* `cp.exec`), or the raw import specifier for `banned-import` (e.g.
|
|
2098
|
+
* `moment/locale/nl`).
|
|
2099
|
+
*/
|
|
2100
|
+
matched: string
|
|
2101
|
+
severity: PolicyViolationSeverity
|
|
2102
|
+
/**
|
|
2103
|
+
* The rule's author-provided message, when set.
|
|
2104
|
+
*/
|
|
2105
|
+
message?: (string | null)
|
|
2106
|
+
/**
|
|
2107
|
+
* Suggested next steps.
|
|
2108
|
+
*/
|
|
2109
|
+
actions: IssueAction[]
|
|
2110
|
+
/**
|
|
2111
|
+
* Set by the audit pass when this finding is introduced relative to
|
|
2112
|
+
* the merge-base.
|
|
2113
|
+
*/
|
|
2114
|
+
introduced?: (AuditIntroduced | null)
|
|
2115
|
+
}
|
|
1820
2116
|
/**
|
|
1821
2117
|
* A suppression comment or JSDoc tag that no longer matches any issue.
|
|
1822
2118
|
*/
|
|
@@ -2150,73 +2446,6 @@ exceeded: boolean
|
|
|
2150
2446
|
*/
|
|
2151
2447
|
reason?: (string | null)
|
|
2152
2448
|
}
|
|
2153
|
-
/**
|
|
2154
|
-
* Metric and rule definitions emitted under `_meta` when `--explain` is
|
|
2155
|
-
* passed (always present in MCP responses). Helps AI agents and CI systems
|
|
2156
|
-
* interpret metric values without re-reading the docs site.
|
|
2157
|
-
*/
|
|
2158
|
-
export interface Meta {
|
|
2159
|
-
/**
|
|
2160
|
-
* URL to the documentation page for this command.
|
|
2161
|
-
*/
|
|
2162
|
-
docs?: (string | null)
|
|
2163
|
-
/**
|
|
2164
|
-
* Per-field definitions for envelope fields and action payload fields.
|
|
2165
|
-
*/
|
|
2166
|
-
field_definitions?: {
|
|
2167
|
-
[k: string]: string
|
|
2168
|
-
}
|
|
2169
|
-
/**
|
|
2170
|
-
* Per-metric definitions: name, description, range, interpretation.
|
|
2171
|
-
*/
|
|
2172
|
-
metrics?: {
|
|
2173
|
-
[k: string]: MetaMetric
|
|
2174
|
-
}
|
|
2175
|
-
/**
|
|
2176
|
-
* Per-rule definitions for check command output.
|
|
2177
|
-
*/
|
|
2178
|
-
rules?: {
|
|
2179
|
-
[k: string]: MetaRule
|
|
2180
|
-
}
|
|
2181
|
-
}
|
|
2182
|
-
/**
|
|
2183
|
-
* Single-metric definition inside [`Meta::metrics`].
|
|
2184
|
-
*/
|
|
2185
|
-
export interface MetaMetric {
|
|
2186
|
-
/**
|
|
2187
|
-
* Human-readable metric name.
|
|
2188
|
-
*/
|
|
2189
|
-
name?: (string | null)
|
|
2190
|
-
/**
|
|
2191
|
-
* What this metric measures and how it is computed.
|
|
2192
|
-
*/
|
|
2193
|
-
description?: (string | null)
|
|
2194
|
-
/**
|
|
2195
|
-
* Valid value range (e.g., `"[0, 100]"`).
|
|
2196
|
-
*/
|
|
2197
|
-
range?: (string | null)
|
|
2198
|
-
/**
|
|
2199
|
-
* How to read the value (e.g., `"lower is better"`).
|
|
2200
|
-
*/
|
|
2201
|
-
interpretation?: (string | null)
|
|
2202
|
-
}
|
|
2203
|
-
/**
|
|
2204
|
-
* Single-rule definition inside [`Meta::rules`].
|
|
2205
|
-
*/
|
|
2206
|
-
export interface MetaRule {
|
|
2207
|
-
/**
|
|
2208
|
-
* Human-readable rule name.
|
|
2209
|
-
*/
|
|
2210
|
-
name?: (string | null)
|
|
2211
|
-
/**
|
|
2212
|
-
* What this rule detects.
|
|
2213
|
-
*/
|
|
2214
|
-
description?: (string | null)
|
|
2215
|
-
/**
|
|
2216
|
-
* URL to the rule documentation.
|
|
2217
|
-
*/
|
|
2218
|
-
docs?: (string | null)
|
|
2219
|
-
}
|
|
2220
2449
|
/**
|
|
2221
2450
|
* Wire-shape payload for `fallow dupes --format json` (the body that
|
|
2222
2451
|
* flattens into [`crate::output_envelope::DupesOutput`] and is also
|
|
@@ -2757,7 +2986,7 @@ severity_high_count: number
|
|
|
2757
2986
|
severity_moderate_count: number
|
|
2758
2987
|
}
|
|
2759
2988
|
/**
|
|
2760
|
-
* Project-wide vital signs
|
|
2989
|
+
* Project-wide vital signs , a fixed set of metrics for trend tracking.
|
|
2761
2990
|
*
|
|
2762
2991
|
* Metrics are `Option` when the data source was not available in the current run
|
|
2763
2992
|
* (e.g., `duplication_pct` is `None` unless the duplication pipeline was run,
|
|
@@ -3298,7 +3527,7 @@ coverage_percent: number
|
|
|
3298
3527
|
trace_count: number
|
|
3299
3528
|
/**
|
|
3300
3529
|
* Days of observation covered by the supplied dump (Phase 2 local analysis
|
|
3301
|
-
* emits 0
|
|
3530
|
+
* emits 0 , set by the beacon/cloud in Phase 3+).
|
|
3302
3531
|
*/
|
|
3303
3532
|
period_days: number
|
|
3304
3533
|
/**
|
|
@@ -3760,6 +3989,14 @@ complex_functions?: EvidenceFunction[]
|
|
|
3760
3989
|
* Files forming the import cycle (populated for `BreakCircularDependency` targets).
|
|
3761
3990
|
*/
|
|
3762
3991
|
cycle_path?: string[]
|
|
3992
|
+
/**
|
|
3993
|
+
* Files that directly import this target, with imported and local symbols.
|
|
3994
|
+
*/
|
|
3995
|
+
direct_callers?: DirectCallerEvidence[]
|
|
3996
|
+
/**
|
|
3997
|
+
* Other duplicate-code instances that share a clone group with this target.
|
|
3998
|
+
*/
|
|
3999
|
+
clone_siblings?: CloneSiblingEvidence[]
|
|
3763
4000
|
}
|
|
3764
4001
|
/**
|
|
3765
4002
|
* A function referenced in target evidence.
|
|
@@ -3778,6 +4015,57 @@ line: number
|
|
|
3778
4015
|
*/
|
|
3779
4016
|
cognitive: number
|
|
3780
4017
|
}
|
|
4018
|
+
/**
|
|
4019
|
+
* A direct importer referenced in target evidence.
|
|
4020
|
+
*/
|
|
4021
|
+
export interface DirectCallerEvidence {
|
|
4022
|
+
/**
|
|
4023
|
+
* File that directly imports the target.
|
|
4024
|
+
*/
|
|
4025
|
+
path: string
|
|
4026
|
+
/**
|
|
4027
|
+
* Symbols imported from the target by this file.
|
|
4028
|
+
*/
|
|
4029
|
+
symbols?: DirectCallerSymbolEvidence[]
|
|
4030
|
+
}
|
|
4031
|
+
/**
|
|
4032
|
+
* Symbol details for a direct importer.
|
|
4033
|
+
*/
|
|
4034
|
+
export interface DirectCallerSymbolEvidence {
|
|
4035
|
+
/**
|
|
4036
|
+
* Imported binding name.
|
|
4037
|
+
*/
|
|
4038
|
+
imported: string
|
|
4039
|
+
/**
|
|
4040
|
+
* Local binding name in the importing file.
|
|
4041
|
+
*/
|
|
4042
|
+
local: string
|
|
4043
|
+
/**
|
|
4044
|
+
* Whether the import is type-only.
|
|
4045
|
+
*/
|
|
4046
|
+
type_only: boolean
|
|
4047
|
+
}
|
|
4048
|
+
/**
|
|
4049
|
+
* A duplicate-code sibling referenced in target evidence.
|
|
4050
|
+
*/
|
|
4051
|
+
export interface CloneSiblingEvidence {
|
|
4052
|
+
/**
|
|
4053
|
+
* File containing the sibling clone instance.
|
|
4054
|
+
*/
|
|
4055
|
+
path: string
|
|
4056
|
+
/**
|
|
4057
|
+
* 1-based start line of the sibling clone.
|
|
4058
|
+
*/
|
|
4059
|
+
start_line: number
|
|
4060
|
+
/**
|
|
4061
|
+
* 1-based end line of the sibling clone.
|
|
4062
|
+
*/
|
|
4063
|
+
end_line: number
|
|
4064
|
+
/**
|
|
4065
|
+
* Stable duplicate-group handle, matching `dupes --trace dup:<id>`.
|
|
4066
|
+
*/
|
|
4067
|
+
fingerprint: string
|
|
4068
|
+
}
|
|
3781
4069
|
/**
|
|
3782
4070
|
* Suggested action attached to a [`RefactoringTarget`].
|
|
3783
4071
|
*
|
|
@@ -4711,6 +4999,25 @@ re_export_cycles?: ReExportCycleFinding[]
|
|
|
4711
4999
|
* array natively.
|
|
4712
5000
|
*/
|
|
4713
5001
|
boundary_violations?: BoundaryViolationFinding[]
|
|
5002
|
+
/**
|
|
5003
|
+
* Files that matched no architecture boundary zone while
|
|
5004
|
+
* `boundaries.coverage.requireAllFiles` was enabled.
|
|
5005
|
+
*/
|
|
5006
|
+
boundary_coverage_violations?: BoundaryCoverageViolationFinding[]
|
|
5007
|
+
/**
|
|
5008
|
+
* Calls from zoned files to callees forbidden for that zone via
|
|
5009
|
+
* `boundaries.calls.forbidden`. Wrapped in
|
|
5010
|
+
* [`BoundaryCallViolationFinding`] so each entry carries a typed
|
|
5011
|
+
* `actions` array natively.
|
|
5012
|
+
*/
|
|
5013
|
+
boundary_call_violations?: BoundaryCallViolationFinding[]
|
|
5014
|
+
/**
|
|
5015
|
+
* Banned calls and banned imports matched by declarative rule packs
|
|
5016
|
+
* (`rulePacks` config). Wrapped in [`PolicyViolationFinding`] so each
|
|
5017
|
+
* entry carries a typed `actions` array natively. Each finding carries
|
|
5018
|
+
* its effective per-rule severity.
|
|
5019
|
+
*/
|
|
5020
|
+
policy_violations?: PolicyViolationFinding[]
|
|
4714
5021
|
/**
|
|
4715
5022
|
* Suppression comments or JSDoc tags that no longer match any issue.
|
|
4716
5023
|
*/
|
|
@@ -4762,6 +5069,7 @@ export interface ImpactReport {
|
|
|
4762
5069
|
schema_version: ImpactReportSchemaVersion
|
|
4763
5070
|
enabled: boolean
|
|
4764
5071
|
record_count: number
|
|
5072
|
+
_meta?: (Meta | null)
|
|
4765
5073
|
first_recorded?: (string | null)
|
|
4766
5074
|
/**
|
|
4767
5075
|
* Git SHA of the most recent recorded run, so a consumer can tell which
|
|
@@ -4863,6 +5171,13 @@ timestamp: string
|
|
|
4863
5171
|
*/
|
|
4864
5172
|
export interface SecurityOutput {
|
|
4865
5173
|
schema_version: SecuritySchemaVersion
|
|
5174
|
+
version: ToolVersion
|
|
5175
|
+
elapsed_ms: ElapsedMs
|
|
5176
|
+
config: SecurityOutputConfig
|
|
5177
|
+
/**
|
|
5178
|
+
* Security-specific rule and field metadata, emitted with `--explain`.
|
|
5179
|
+
*/
|
|
5180
|
+
_meta?: (Meta | null)
|
|
4866
5181
|
/**
|
|
4867
5182
|
* Gate verdict, present only when `--gate <mode>` was set (issue #886).
|
|
4868
5183
|
* Emitted on pass too (`verdict: "pass"`, `new_count: 0`) so consumers
|
|
@@ -4892,6 +5207,34 @@ unresolved_edge_files: number
|
|
|
4892
5207
|
* here is NOT a clean bill.
|
|
4893
5208
|
*/
|
|
4894
5209
|
unresolved_callee_sites: number
|
|
5210
|
+
/**
|
|
5211
|
+
* Bounded diagnostics for unresolved callee blind spots.
|
|
5212
|
+
*/
|
|
5213
|
+
unresolved_callee_diagnostics?: (SecurityUnresolvedCalleeDiagnostics | null)
|
|
5214
|
+
}
|
|
5215
|
+
/**
|
|
5216
|
+
* Allowlisted config context for `fallow security --format json`.
|
|
5217
|
+
*/
|
|
5218
|
+
export interface SecurityOutputConfig {
|
|
5219
|
+
rules: SecurityOutputRulesConfig
|
|
5220
|
+
/**
|
|
5221
|
+
* `security.categories.include` from config. `null` means unset, `[]`
|
|
5222
|
+
* means explicitly empty.
|
|
5223
|
+
*/
|
|
5224
|
+
categories_include: (string[] | null)
|
|
5225
|
+
/**
|
|
5226
|
+
* `security.categories.exclude` from config. `null` means unset, `[]`
|
|
5227
|
+
* means explicitly empty.
|
|
5228
|
+
*/
|
|
5229
|
+
categories_exclude: (string[] | null)
|
|
5230
|
+
}
|
|
5231
|
+
export interface SecurityOutputRulesConfig {
|
|
5232
|
+
security_client_server_leak: SecurityRuleSeverityConfig
|
|
5233
|
+
security_sink: SecurityRuleSeverityConfig
|
|
5234
|
+
}
|
|
5235
|
+
export interface SecurityRuleSeverityConfig {
|
|
5236
|
+
configured: Severity
|
|
5237
|
+
effective: Severity
|
|
4895
5238
|
}
|
|
4896
5239
|
/**
|
|
4897
5240
|
* The `gate` block on `SecurityOutput`, present only when `--gate <mode>` ran.
|
|
@@ -4901,7 +5244,7 @@ export interface SecurityGate {
|
|
|
4901
5244
|
mode: SecurityGateMode
|
|
4902
5245
|
verdict: SecurityGateVerdict
|
|
4903
5246
|
/**
|
|
4904
|
-
* Number of candidates
|
|
5247
|
+
* Number of candidates matching the selected gate mode.
|
|
4905
5248
|
*/
|
|
4906
5249
|
new_count: number
|
|
4907
5250
|
}
|
|
@@ -4960,6 +5303,7 @@ evidence: string
|
|
|
4960
5303
|
* `ClientServerLeak`. Skipped from JSON when `false` for output stability.
|
|
4961
5304
|
*/
|
|
4962
5305
|
source_backed?: boolean
|
|
5306
|
+
severity: SecuritySeverity
|
|
4963
5307
|
/**
|
|
4964
5308
|
* Structural import-hop trace from the client boundary to the secret source.
|
|
4965
5309
|
* The hop count is the uncalibrated signal; fallow does not prove the path
|
|
@@ -5071,6 +5415,15 @@ reachable_from_entry: boolean
|
|
|
5071
5415
|
* not prove a specific source value reaches the sink argument.
|
|
5072
5416
|
*/
|
|
5073
5417
|
reachable_from_untrusted_source?: boolean
|
|
5418
|
+
/**
|
|
5419
|
+
* Structured tier of the untrusted-source association: `arg-level` when the
|
|
5420
|
+
* sink argument traces to a same-module source read (strong), `module-level`
|
|
5421
|
+
* when only the module is import-reachable from a source (weak). Present
|
|
5422
|
+
* exactly when `reachable_from_untrusted_source` is true, so a consumer can
|
|
5423
|
+
* separate strong from weak candidates from this field alone without parsing
|
|
5424
|
+
* the `evidence` string. Not an exploitability proof.
|
|
5425
|
+
*/
|
|
5426
|
+
taint_confidence?: (TaintConfidence | null)
|
|
5074
5427
|
/**
|
|
5075
5428
|
* Number of value-import hops from the untrusted-source module to the sink
|
|
5076
5429
|
* module when `reachable_from_untrusted_source` is true.
|
|
@@ -5099,10 +5452,11 @@ crosses_boundary: boolean
|
|
|
5099
5452
|
/**
|
|
5100
5453
|
* An agent-actionable candidate record on a [`SecurityFinding`]. fallow fills
|
|
5101
5454
|
* `source_kind`, `sink`, and `boundary`. The exploitability IMPACT is
|
|
5102
|
-
* deliberately NOT a field:
|
|
5103
|
-
*
|
|
5104
|
-
*
|
|
5105
|
-
* own impact verdict
|
|
5455
|
+
* deliberately NOT a field: `severity` on the parent finding is only a
|
|
5456
|
+
* review-priority tier, while deciding exploitability remains the consuming
|
|
5457
|
+
* agent's job. A perpetually-null `impact` key would only train consumers to
|
|
5458
|
+
* ignore it. The agent reads this record, then writes its own impact verdict
|
|
5459
|
+
* downstream.
|
|
5106
5460
|
*/
|
|
5107
5461
|
export interface SecurityCandidate {
|
|
5108
5462
|
/**
|
|
@@ -5161,6 +5515,12 @@ cwe?: (number | null)
|
|
|
5161
5515
|
* `None` for `client-server-leak` and matches that name no callee.
|
|
5162
5516
|
*/
|
|
5163
5517
|
callee?: (string | null)
|
|
5518
|
+
/**
|
|
5519
|
+
* URL construction shape for SSRF and open-redirect style candidates when
|
|
5520
|
+
* fallow can classify whether the origin is fixed or dynamic. Absent for
|
|
5521
|
+
* non-URL sinks and unclassified URL expressions.
|
|
5522
|
+
*/
|
|
5523
|
+
url_shape?: (SecurityUrlShape | null)
|
|
5164
5524
|
}
|
|
5165
5525
|
/**
|
|
5166
5526
|
* The boundary slot of a [`SecurityCandidate`]: which structural boundaries the
|
|
@@ -5346,6 +5706,155 @@ col: number
|
|
|
5346
5706
|
*/
|
|
5347
5707
|
callee: string
|
|
5348
5708
|
}
|
|
5709
|
+
/**
|
|
5710
|
+
* Bounded unresolved-callee diagnostics for `fallow security --format json`.
|
|
5711
|
+
*/
|
|
5712
|
+
export interface SecurityUnresolvedCalleeDiagnostics {
|
|
5713
|
+
/**
|
|
5714
|
+
* Deterministic sample rows, capped by `sample_limit`.
|
|
5715
|
+
*/
|
|
5716
|
+
sampled: SecurityUnresolvedCalleeSample[]
|
|
5717
|
+
/**
|
|
5718
|
+
* Files with the most unresolved callees, capped by `top_files_limit`.
|
|
5719
|
+
*/
|
|
5720
|
+
top_files: SecurityUnresolvedCalleeTopFile[]
|
|
5721
|
+
/**
|
|
5722
|
+
* Full count by unresolved-callee reason, sorted by count then reason.
|
|
5723
|
+
*/
|
|
5724
|
+
by_reason: SecurityUnresolvedCalleeReasonCount[]
|
|
5725
|
+
/**
|
|
5726
|
+
* Maximum number of sample rows emitted.
|
|
5727
|
+
*/
|
|
5728
|
+
sample_limit: number
|
|
5729
|
+
/**
|
|
5730
|
+
* Maximum number of top-file rows emitted.
|
|
5731
|
+
*/
|
|
5732
|
+
top_files_limit: number
|
|
5733
|
+
}
|
|
5734
|
+
/**
|
|
5735
|
+
* One sampled unresolved-callee row.
|
|
5736
|
+
*/
|
|
5737
|
+
export interface SecurityUnresolvedCalleeSample {
|
|
5738
|
+
/**
|
|
5739
|
+
* Project-relative source path.
|
|
5740
|
+
*/
|
|
5741
|
+
path: string
|
|
5742
|
+
/**
|
|
5743
|
+
* 1-based source line.
|
|
5744
|
+
*/
|
|
5745
|
+
line: number
|
|
5746
|
+
/**
|
|
5747
|
+
* 0-based byte column.
|
|
5748
|
+
*/
|
|
5749
|
+
col: number
|
|
5750
|
+
reason: SkippedSecurityCalleeReason
|
|
5751
|
+
expression_kind: SkippedSecurityCalleeExpressionKind
|
|
5752
|
+
}
|
|
5753
|
+
/**
|
|
5754
|
+
* Count of unresolved callees in one file.
|
|
5755
|
+
*/
|
|
5756
|
+
export interface SecurityUnresolvedCalleeTopFile {
|
|
5757
|
+
/**
|
|
5758
|
+
* Project-relative source path.
|
|
5759
|
+
*/
|
|
5760
|
+
path: string
|
|
5761
|
+
/**
|
|
5762
|
+
* Number of unresolved callees in this file.
|
|
5763
|
+
*/
|
|
5764
|
+
count: number
|
|
5765
|
+
}
|
|
5766
|
+
/**
|
|
5767
|
+
* Count of unresolved callees for one reason.
|
|
5768
|
+
*/
|
|
5769
|
+
export interface SecurityUnresolvedCalleeReasonCount {
|
|
5770
|
+
reason: SkippedSecurityCalleeReason
|
|
5771
|
+
/**
|
|
5772
|
+
* Number of unresolved callees with this reason.
|
|
5773
|
+
*/
|
|
5774
|
+
count: number
|
|
5775
|
+
}
|
|
5776
|
+
/**
|
|
5777
|
+
* Compact `fallow security --summary --format json` payload. Uses the same
|
|
5778
|
+
* `kind: "security"` discriminator as the full payload, but omits candidate
|
|
5779
|
+
* arrays and exposes only aggregate counts.
|
|
5780
|
+
*/
|
|
5781
|
+
export interface SecuritySummaryOutput {
|
|
5782
|
+
schema_version: SecuritySchemaVersion
|
|
5783
|
+
version: ToolVersion
|
|
5784
|
+
elapsed_ms: ElapsedMs
|
|
5785
|
+
config: SecurityOutputConfig
|
|
5786
|
+
/**
|
|
5787
|
+
* Security-specific rule and field metadata, emitted with `--explain`.
|
|
5788
|
+
*/
|
|
5789
|
+
_meta?: (Meta | null)
|
|
5790
|
+
/**
|
|
5791
|
+
* Gate verdict, present only when `--gate <mode>` was set.
|
|
5792
|
+
*/
|
|
5793
|
+
gate?: (SecurityGate | null)
|
|
5794
|
+
summary: SecuritySummary
|
|
5795
|
+
}
|
|
5796
|
+
/**
|
|
5797
|
+
* Aggregate counts for `fallow security --summary --format json`.
|
|
5798
|
+
*/
|
|
5799
|
+
export interface SecuritySummary {
|
|
5800
|
+
/**
|
|
5801
|
+
* Number of security candidates after all filters, gates, and scopes.
|
|
5802
|
+
*/
|
|
5803
|
+
security_findings: number
|
|
5804
|
+
by_severity: SecuritySeverityCounts
|
|
5805
|
+
/**
|
|
5806
|
+
* Finding counts by catalogue category, or by kind for findings without a
|
|
5807
|
+
* catalogue category.
|
|
5808
|
+
*/
|
|
5809
|
+
by_category: {
|
|
5810
|
+
[k: string]: number
|
|
5811
|
+
}
|
|
5812
|
+
by_reachability: SecurityReachabilityCounts
|
|
5813
|
+
by_runtime_state: SecurityRuntimeStateCounts
|
|
5814
|
+
/**
|
|
5815
|
+
* Number of client files whose dynamic imports could not be followed.
|
|
5816
|
+
*/
|
|
5817
|
+
unresolved_edge_files: number
|
|
5818
|
+
/**
|
|
5819
|
+
* Number of sink-shaped callees that could not be statically flattened.
|
|
5820
|
+
*/
|
|
5821
|
+
unresolved_callee_sites: number
|
|
5822
|
+
/**
|
|
5823
|
+
* Number of attack-surface entries included in the prepared full output.
|
|
5824
|
+
*/
|
|
5825
|
+
attack_surface_entries: number
|
|
5826
|
+
}
|
|
5827
|
+
/**
|
|
5828
|
+
* Fixed severity counters for summary JSON.
|
|
5829
|
+
*/
|
|
5830
|
+
export interface SecuritySeverityCounts {
|
|
5831
|
+
high: number
|
|
5832
|
+
medium: number
|
|
5833
|
+
low: number
|
|
5834
|
+
}
|
|
5835
|
+
/**
|
|
5836
|
+
* Fixed reachability counters for summary JSON.
|
|
5837
|
+
*/
|
|
5838
|
+
export interface SecurityReachabilityCounts {
|
|
5839
|
+
entry_reachable: number
|
|
5840
|
+
untrusted_source_reachable: number
|
|
5841
|
+
arg_level: number
|
|
5842
|
+
module_level: number
|
|
5843
|
+
crosses_boundary: number
|
|
5844
|
+
source_backed: number
|
|
5845
|
+
}
|
|
5846
|
+
/**
|
|
5847
|
+
* Fixed runtime coverage counters for summary JSON.
|
|
5848
|
+
*/
|
|
5849
|
+
export interface SecurityRuntimeStateCounts {
|
|
5850
|
+
runtime_hot: number
|
|
5851
|
+
runtime_cold: number
|
|
5852
|
+
never_executed: number
|
|
5853
|
+
low_traffic: number
|
|
5854
|
+
coverage_unavailable: number
|
|
5855
|
+
runtime_unknown: number
|
|
5856
|
+
not_collected: number
|
|
5857
|
+
}
|
|
5349
5858
|
/**
|
|
5350
5859
|
* Bare `fallow --format json` envelope.
|
|
5351
5860
|
*/
|
|
@@ -5362,6 +5871,7 @@ export interface CombinedMeta {
|
|
|
5362
5871
|
check?: (Meta | null)
|
|
5363
5872
|
dupes?: (Meta | null)
|
|
5364
5873
|
health?: (Meta | null)
|
|
5874
|
+
telemetry?: (TelemetryMeta | null)
|
|
5365
5875
|
}
|
|
5366
5876
|
/**
|
|
5367
5877
|
* Single CodeClimate-compatible issue inside [`CodeClimateOutput`].
|