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.
@@ -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>` (issue #886). Tier 2 reserves
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 consider
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 a fixed set of metrics for trend tracking.
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 set by the beacon/cloud in Phase 3+).
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 introduced in the changed lines.
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: deciding severity / exploitability is the consuming
5103
- * agent's job, not fallow's, and a perpetually-null `impact` key would only
5104
- * train consumers to ignore it. The agent reads this record, then writes its
5105
- * own impact verdict downstream.
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`].