code-auditor-mcp 4.0.4 → 4.1.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.
Files changed (155) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +132 -0
  3. package/README.md +5 -5
  4. package/configs/hhra-compat.json +2 -2
  5. package/dist/analyzers/applicability.d.ts +25 -2
  6. package/dist/analyzers/applicability.d.ts.map +1 -1
  7. package/dist/analyzers/applicability.js +44 -50
  8. package/dist/analyzers/applicability.js.map +1 -1
  9. package/dist/analyzers/cross-language/APIContractAnalyzer.d.ts +18 -49
  10. package/dist/analyzers/cross-language/APIContractAnalyzer.d.ts.map +1 -1
  11. package/dist/analyzers/cross-language/APIContractAnalyzer.js +22 -240
  12. package/dist/analyzers/cross-language/APIContractAnalyzer.js.map +1 -1
  13. package/dist/analyzers/cross-language/SchemaValidator.d.ts +2 -14
  14. package/dist/analyzers/cross-language/SchemaValidator.d.ts.map +1 -1
  15. package/dist/analyzers/cross-language/SchemaValidator.js +0 -104
  16. package/dist/analyzers/cross-language/SchemaValidator.js.map +1 -1
  17. package/dist/analyzers/orgFilterTiers.d.ts +89 -0
  18. package/dist/analyzers/orgFilterTiers.d.ts.map +1 -0
  19. package/dist/analyzers/orgFilterTiers.js +96 -0
  20. package/dist/analyzers/orgFilterTiers.js.map +1 -0
  21. package/dist/analyzers/ruleRegistry.d.ts +15 -0
  22. package/dist/analyzers/ruleRegistry.d.ts.map +1 -1
  23. package/dist/analyzers/ruleRegistry.js +139 -185
  24. package/dist/analyzers/ruleRegistry.js.map +1 -1
  25. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts +1 -12
  26. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
  27. package/dist/analyzers/universal/UniversalDRYAnalyzer.js +1 -66
  28. package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
  29. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts +39 -0
  30. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts.map +1 -1
  31. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js +62 -41
  32. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js.map +1 -1
  33. package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts +2 -2
  34. package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts.map +1 -1
  35. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js +2 -2
  36. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js.map +1 -1
  37. package/dist/analyzers/universal/UniversalSecurityAnalyzer.d.ts +86 -0
  38. package/dist/analyzers/universal/UniversalSecurityAnalyzer.d.ts.map +1 -0
  39. package/dist/analyzers/universal/UniversalSecurityAnalyzer.js +606 -0
  40. package/dist/analyzers/universal/UniversalSecurityAnalyzer.js.map +1 -0
  41. package/dist/analyzers/universal/schema/codeAnalysis.d.ts +14 -0
  42. package/dist/analyzers/universal/schema/codeAnalysis.d.ts.map +1 -1
  43. package/dist/analyzers/universal/schema/codeAnalysis.js +35 -18
  44. package/dist/analyzers/universal/schema/codeAnalysis.js.map +1 -1
  45. package/dist/analyzers/universal/schema/migrations.d.ts +14 -1
  46. package/dist/analyzers/universal/schema/migrations.d.ts.map +1 -1
  47. package/dist/analyzers/universal/schema/migrations.js +58 -14
  48. package/dist/analyzers/universal/schema/migrations.js.map +1 -1
  49. package/dist/auditRunner.d.ts.map +1 -1
  50. package/dist/auditRunner.js +71 -33
  51. package/dist/auditRunner.js.map +1 -1
  52. package/dist/churn/churnExtractor.js +5 -5
  53. package/dist/churn/churnExtractor.js.map +1 -1
  54. package/dist/cli.js +75 -26
  55. package/dist/cli.js.map +1 -1
  56. package/dist/codeIndexDB.d.ts +7 -9
  57. package/dist/codeIndexDB.d.ts.map +1 -1
  58. package/dist/codeIndexDB.js +33 -21
  59. package/dist/codeIndexDB.js.map +1 -1
  60. package/dist/config/configGeneratePath.d.ts +19 -0
  61. package/dist/config/configGeneratePath.d.ts.map +1 -0
  62. package/dist/config/configGeneratePath.js +29 -0
  63. package/dist/config/configGeneratePath.js.map +1 -0
  64. package/dist/config/configLoader.d.ts +36 -4
  65. package/dist/config/configLoader.d.ts.map +1 -1
  66. package/dist/config/configLoader.js +141 -16
  67. package/dist/config/configLoader.js.map +1 -1
  68. package/dist/config/defaults.d.ts.map +1 -1
  69. package/dist/config/defaults.js +5 -6
  70. package/dist/config/defaults.js.map +1 -1
  71. package/dist/config/lintConfigReader.d.ts +4 -0
  72. package/dist/config/lintConfigReader.d.ts.map +1 -1
  73. package/dist/config/lintConfigReader.js +35 -36
  74. package/dist/config/lintConfigReader.js.map +1 -1
  75. package/dist/config/staticObjectExtract.d.ts +35 -0
  76. package/dist/config/staticObjectExtract.d.ts.map +1 -0
  77. package/dist/config/staticObjectExtract.js +312 -0
  78. package/dist/config/staticObjectExtract.js.map +1 -0
  79. package/dist/constants.d.ts +1 -2
  80. package/dist/constants.d.ts.map +1 -1
  81. package/dist/constants.js +10 -7
  82. package/dist/constants.js.map +1 -1
  83. package/dist/daemon/core.js +1 -1
  84. package/dist/daemon/core.js.map +1 -1
  85. package/dist/daemon/main.js +1 -1
  86. package/dist/daemon/main.js.map +1 -1
  87. package/dist/daemon/resolve.d.ts +4 -4
  88. package/dist/daemon/resolve.js +4 -4
  89. package/dist/dataPaths.d.ts +10 -0
  90. package/dist/dataPaths.d.ts.map +1 -1
  91. package/dist/dataPaths.js +23 -2
  92. package/dist/dataPaths.js.map +1 -1
  93. package/dist/generators/BaseConfigGenerator.d.ts +0 -4
  94. package/dist/generators/BaseConfigGenerator.d.ts.map +1 -1
  95. package/dist/generators/BaseConfigGenerator.js +1 -7
  96. package/dist/generators/BaseConfigGenerator.js.map +1 -1
  97. package/dist/installConfig.d.ts +3 -1
  98. package/dist/installConfig.d.ts.map +1 -1
  99. package/dist/installConfig.js +15 -2
  100. package/dist/installConfig.js.map +1 -1
  101. package/dist/installer.d.ts +10 -0
  102. package/dist/installer.d.ts.map +1 -1
  103. package/dist/installer.js +14 -2
  104. package/dist/installer.js.map +1 -1
  105. package/dist/languages/LanguageOrchestrator.js +6 -6
  106. package/dist/languages/LanguageOrchestrator.js.map +1 -1
  107. package/dist/languages/RuntimeManager.js +13 -10
  108. package/dist/languages/RuntimeManager.js.map +1 -1
  109. package/dist/mcp-tools-shared.d.ts.map +1 -1
  110. package/dist/mcp-tools-shared.js +7 -2
  111. package/dist/mcp-tools-shared.js.map +1 -1
  112. package/dist/mcp-ui-simple.d.ts +5 -1
  113. package/dist/mcp-ui-simple.d.ts.map +1 -1
  114. package/dist/mcp-ui-simple.js +81 -29
  115. package/dist/mcp-ui-simple.js.map +1 -1
  116. package/dist/mcp.js +25 -6
  117. package/dist/mcp.js.map +1 -1
  118. package/dist/mcpAuditJobs.d.ts.map +1 -1
  119. package/dist/mcpAuditJobs.js +1 -0
  120. package/dist/mcpAuditJobs.js.map +1 -1
  121. package/dist/nextFileIncremental.js +1 -1
  122. package/dist/nextFileIncremental.js.map +1 -1
  123. package/dist/pipeline.d.ts.map +1 -1
  124. package/dist/pipeline.js +13 -2
  125. package/dist/pipeline.js.map +1 -1
  126. package/dist/pipelineAdapters.d.ts +16 -1
  127. package/dist/pipelineAdapters.d.ts.map +1 -1
  128. package/dist/pipelineAdapters.js +142 -11
  129. package/dist/pipelineAdapters.js.map +1 -1
  130. package/dist/reporting/htmlReportGenerator.js +2 -2
  131. package/dist/reporting/htmlReportGenerator.js.map +1 -1
  132. package/dist/ruleAliases.d.ts.map +1 -1
  133. package/dist/ruleAliases.js +45 -0
  134. package/dist/ruleAliases.js.map +1 -1
  135. package/dist/styles/tailwindConfigLoader.d.ts +4 -0
  136. package/dist/styles/tailwindConfigLoader.d.ts.map +1 -1
  137. package/dist/styles/tailwindConfigLoader.js +54 -36
  138. package/dist/styles/tailwindConfigLoader.js.map +1 -1
  139. package/dist/types.d.ts +60 -23
  140. package/dist/types.d.ts.map +1 -1
  141. package/dist/types.js +15 -0
  142. package/dist/types.js.map +1 -1
  143. package/dist/version.generated.d.ts +1 -1
  144. package/dist/version.generated.js +1 -1
  145. package/examples/.auditrc.example.json +2 -2
  146. package/examples/.auditrc.json +3 -3
  147. package/examples/nextjs.auditrc.json +1 -1
  148. package/examples/node-api.auditrc.json +1 -1
  149. package/examples/react.auditrc.json +2 -2
  150. package/examples/tolerant-solid.auditrc.json +1 -1
  151. package/package.json +5 -4
  152. package/plugin/.claude-plugin/plugin.json +1 -1
  153. package/plugin/scripts/hook-common.sh +27 -27
  154. package/plugin/skills/code-auditor/SKILL.md +1 -1
  155. package/server.json +2 -2
@@ -10,7 +10,7 @@
10
10
  "name": "code-auditor",
11
11
  "source": "./plugin",
12
12
  "description": "Diff-scoped code quality auditing on every edit. Indexes your codebase, enforces invariants, and feeds violations back to the agent so fixes happen inline.",
13
- "version": "4.0.4",
13
+ "version": "4.1.1",
14
14
  "author": {
15
15
  "name": "Ben Hammond"
16
16
  },
package/CHANGELOG.md CHANGED
@@ -2,6 +2,138 @@
2
2
 
3
3
  All notable changes to the Code Auditor MCP project.
4
4
 
5
+ ## [4.1.1] — 2026-09-23
6
+
7
+ ### Report writes stop destroying files
8
+
9
+ **4.1.0 and earlier overwrote `audit-report.json` in the audited project's root
10
+ without asking; 4.1.1 writes to stdout unless `-o` is passed and refuses to
11
+ clobber.** Anyone who ran a formatted audit in a repo with that filename should
12
+ check their history.
13
+
14
+ - `audit --format` no longer defaults its output path to `process.cwd()`: with no
15
+ `-o` it writes the report to stdout, and with `-o` it refuses to overwrite an
16
+ existing `audit-report.{ext}` unless `--overwrite` is passed.
17
+ - `map -o <file>` gets the same guard — it no longer silently clobbers an
18
+ existing file.
19
+ - A file-config-supplied `outputDirectory`/`outputDir` is refused outright
20
+ (`output-directory-refused`) rather than clamped into the project tree.
21
+ - `outputFormats`/`outputDirectory` removed from the defaults and `print-config`
22
+ — they were advertised but never consumed for writes.
23
+ - The MCP dev log (`mcp-server.log`) no longer keys off `NODE_ENV`/`DEBUG` (a
24
+ consumer dev shell could trip it) and no longer lands in `process.cwd()`; it
25
+ is opt-in via `--dev` and routed to the OS cache.
26
+ - Consent flag unified: `--overwrite` is the spelling across `audit`, `map`, and
27
+ `generate-config` (`--force`/`--yes` remain as aliases).
28
+
29
+ ### Cross-file duplicate detection never worked — the dead load is gone
30
+
31
+ Cross-file `dry/duplicate` detection was advertised as a "problems only visible
32
+ between files" feature, but it **never fired**: the index stored the
33
+ `statement_block` text while the DRY analyzer hashed the full function node, so
34
+ the comparison could not match. The only thing the comparison ever did was load
35
+ every function body into memory on every single-file `changed` run —
36
+ O(whole-project) per save, for zero findings. The load is deleted (no schema
37
+ change, no migration, no `dry_hash` column); `dry/duplicate` remains, and remains
38
+ correct, as a **within-file** rule. A structural guard now asserts the scoped
39
+ path issues no whole-table `functions` read, so the load can't quietly return.
40
+
41
+ ## [4.1.0] — 2026-09-23
42
+
43
+ ### Severity becomes a three-tier urgency ladder, not a permission knob
44
+
45
+ The `warning`/`suggestion` vocabulary that leaked from the old linter semantics
46
+ is gone. Every finding is now `critical`, `severe`, or `high` — three defect
47
+ tiers with nothing below `high` — and the agent gate blocks **all three**. The
48
+ old per-rule severity knobs (`gateSeverities`, `DEFAULT_BLOCKING_SEVERITIES`,
49
+ `severityOverrides`, and path-profile severity capping) are deleted: a team that
50
+ disagrees with a level scopes the finding out of the gate (`excludeFromGate`) or
51
+ edits the rule, it never re-labels severity.
52
+
53
+ - **102 live severity rules** re-assigned on the urgency axis — 11 `critical`, 37
54
+ `severe`, 54 `high` — one row per rule with rationale in
55
+ `specs/severity-assignment-ledger.md`, plus 4 off-ladder diagnostics.
56
+ - `--fail-on` and `excludeFromGate` remain — they are *scope* controls, not level
57
+ controls.
58
+ - Stale `warning`/`suggestion` literals swept from the shipped configs, README,
59
+ CONTRIBUTING, and the 78 corpus `expected.json` fixtures; a new
60
+ `examplesValidate.spec.ts` loads every shipped example through `loadConfig`, so
61
+ a stale value regresses to a red test rather than silently shipping.
62
+
63
+ ### Ten rules that could never fire are removed, not kept as standing no-ops
64
+
65
+ A rule with no reachable emission site is a finding about the analyzer, not a
66
+ rule to assign severity to. Six `api-contract` rules, the schema `file-error`,
67
+ and three schema-validator aliases (`field-mismatch`, `constraint-mismatch`,
68
+ `version-mismatch`) had exactly that shape — a legacy alias or a predicate
69
+ reading a field no extractor ever populated — so they were deleted outright
70
+ (registry entry, emitter, and ledger row). The ten IDs are tombstoned in
71
+ `ruleAliases.ts` so a stale reference reports *why* each was removed. The
72
+ `cannot-fire` class drops 10 → 0; `APIContractAnalyzer` is now a no-op returning
73
+ `[]`, pending real endpoint/call extraction.
74
+
75
+ ### `missing-org-filter` fires where it should: hhra-org 0 → 9
76
+
77
+ The rule was *applicable* on a DDL-declared multi-tenant corpus (hhra-org) yet
78
+ *fired zero findings* — a false `clean` on a real tenant-isolation leak. Firing
79
+ and applicability had drifted to two different tenancy predicates. Both now
80
+ derive from a single `buildOrgFilterTierSet`, and the rule moved to Stage 4,
81
+ where the DDL-discovered tenant columns live. hhra-org now reports 9
82
+ `missing-org-filter` findings (was 0), and the exact `organization_id = $n`
83
+ positional shape is pinned in a fixture so the long-form column case can't go
84
+ vacuous again. Severity stays `critical` — no provenance tier (recorded, not
85
+ assumed).
86
+
87
+ ### `unescaped-html-interpolation` stops trusting what a string *looks* like
88
+
89
+ The rule used to fire on any template literal whose text contained an HTML tag —
90
+ which flagged a react-analyzer violation *message* as stored XSS and missed 8
91
+ real sinks. It now computes flow: `computeHtmlSinkTemplates` backward-propagates
92
+ from genuine HTML sinks to find which template values actually reach one. The
93
+ sink set is completed to include `setHTMLUnsafe`, Vue `v-html`, the jQuery/Hono
94
+ `.html(x)` setter, and React `dangerouslySetInnerHTML`. The old text trigger's 77
95
+ false positives across corpora are gone; the one real delta is `endless-guessing`
96
+ 0 → 3 (a Hono `c.html(…)` sink).
97
+
98
+ ### The self-audit gate actually enforces all three tiers now
99
+
100
+ `verify:self`'s blocking predicate had drifted to `critical | severe` — a
101
+ two-tier narrowing that let `high` findings through the ratchet (itself a second
102
+ bug on top of the earlier `'warning'` fix). It now matches `BLOCKING_SEVERITIES`
103
+ (`critical | severe | high`). Re-running surfaced 7 in-scope findings, resolved
104
+ as 4 fixes (including splitting `computeHtmlSinkTemplates`' fused visitor into
105
+ three single-purpose phases) and 3 correct-by-design `(file, rule)` scoped
106
+ exemptions with written rationale — excluded *by scope*, never by re-labelling
107
+ severity. The exemptions are now also self-policing: `verify:self` fails on any
108
+ exemption whose `(file, rule)` pair no longer fires, so a suppression can't
109
+ outlive the finding it suppressed (the `SKIP_RULES` failure mode).
110
+
111
+ ### Gate-liveness tests (Spec 62 R9)
112
+
113
+ A gate that "passes" because it checks nothing is the same defect shape as
114
+ `missing-org-filter` — a clean result from a check that isn't there. New
115
+ `gate-liveness.test.ts` proves each gate's failure branch is live: `verify:self`'s
116
+ predicate (extracted to `verify-self-core.mjs`), `verify:disk-space`,
117
+ `verify:gate-budget`, and `assert_compatible` each exit non-zero against their
118
+ own trigger, so a gate can no longer silently pass by checking nothing.
119
+
120
+ ### Registry ↔ ledger reconciliation
121
+
122
+ The rule registry and the authenticity/severity ledgers are now reconciled
123
+ bidirectionally — registry ids with no ledger row, ledger rows with no registry
124
+ id, and the two unregistered-live emit sites are pinned by a membership test so
125
+ the two books can't drift apart.
126
+
127
+ ### Release-rail changes
128
+
129
+ - **`bench` removed from `verify:close`** — it is a measurement, not a gate. The
130
+ close gate is now `verify:disk-space && verify:types && verify:dist-fresh &&
131
+ test && test:integration && verify:gate-budget && verify:clean-install &&
132
+ verify:dist && verify:self`.
133
+ - `verify:gate-budget` and `verify:disk-space` gained env overrides
134
+ (`VERIFY_GATE_BUDGET_MS`, `VERIFY_MIN_FREE_BYTES`) so their failure branches are
135
+ testable without a genuinely slow rule or a genuinely full disk.
136
+
5
137
  ## [4.0.4] — 2026-09-20
6
138
 
7
139
  ### Go analysis now works everywhere, not just Intel Macs
package/README.md CHANGED
@@ -92,7 +92,7 @@ Code Auditor's built-in rules fall into two categories:
92
92
  | **Deterministic** | Structural fact — an engineer would act on every finding | `single-responsibility` (300-line functions), `solid/method-complexity` (cyclomatic complexity > 20), `solid/class-size` (40+ method classes), `dependency-inversion` (concrete imports where an interface exists) |
93
93
  | **Advisory** | Heuristic signal — may be wrong depending on domain | `sql-injection-risk` (AST-level string-pattern matching without type info), `missing-org-filter` (domain-specific — assumes SaaS tenant isolation), `unknown-table` (requires user-provided schema), `dry/duplicate` (token-identical blocks) |
94
94
 
95
- Deterministic rules ship at `critical` or `warning`. Advisory rules ship at `warning` or `suggestion`. Rules proven near-zero precision on a real corpus are **disabled by default** (`off`) — users opt in when the rule matches their domain.
95
+ Deterministic rules ship at `critical` or `severe`. Advisory rules ship at `severe` or `high`. Rules proven near-zero precision on a real corpus are **disabled by default** (`off`) — users opt in when the rule matches their domain.
96
96
 
97
97
  ### Recalibration
98
98
 
@@ -103,9 +103,9 @@ Every disabled rule documents what corpus it *would* be useful on. Users can res
103
103
  ```json
104
104
  {
105
105
  "severityOverrides": {
106
- "sql-injection-risk": "warning",
107
- "missing-org-filter": "critical",
108
- "loop-query": "warning"
106
+ "sql-injection-risk": "critical",
107
+ "missing-org-filter": "severe",
108
+ "loop-query": "severe"
109
109
  }
110
110
  }
111
111
  ```
@@ -195,7 +195,7 @@ code-audit search "mechanism:inline css:color" # inline color declarati
195
195
  code-audit search "token:--color-primary" # bypassing a design token
196
196
  ```
197
197
 
198
- **The React analyzer** also gains raw-element detection: if your project has a `Button` wrapper, raw `<button>` usages outside `Button`'s definition become warnings.
198
+ **The React analyzer** also gains raw-element detection: if your project has a `Button` wrapper, raw `<button>` usages outside `Button`'s definition become severe findings.
199
199
 
200
200
  ## License
201
201
 
@@ -24,7 +24,7 @@
24
24
  ],
25
25
 
26
26
  "enabledAnalyzers": [
27
- "component",
27
+ "react",
28
28
  "security",
29
29
  "solid",
30
30
  "dry",
@@ -138,7 +138,7 @@
138
138
  "outputFormats": ["html", "json"],
139
139
  "outputDirectory": "./audit-reports",
140
140
 
141
- "minSeverity": "suggestion",
141
+ "minSeverity": "high",
142
142
  "failOnCritical": false,
143
143
  "verbose": false,
144
144
  "showProgress": true,
@@ -13,6 +13,11 @@
13
13
  * UniversalSchemaAnalyzer.js → makeVisitorStatus), so a static analyzer import
14
14
  * here would create a pipeline↔analyzer cycle. The pipeline-side convention is
15
15
  * to reach analyzers only through dynamic import() (see pipelineAdapters.ts).
16
+ *
17
+ * The one exception is {@link orgFilterTiers}: a pure, dependency-free module
18
+ * that is the single source of truth for tenant-scoping tiers. Both this
19
+ * applicability predicate and the Stage-4 missing-org-filter reducer derive
20
+ * from it, so firing and applicability can never read different tier sets.
16
21
  */
17
22
  export interface RuleApplicability {
18
23
  applicable: boolean;
@@ -85,11 +90,12 @@ export interface UnreadStyleSourceInfo {
85
90
  *
86
91
  * @param ruleId The registry rule id.
87
92
  * @param dataAccessConfig The namespaced data-access config (may be undefined).
88
- * @param ddlColumns Aggregated DDL-declared columns from the schema reducer.
93
+ * @param ddlTableColumns Aggregated DDL-declared per-table columns from the
94
+ * schema reducer (`Record<table, columns>`), folded corpus-wide.
89
95
  * @returns The rule's applicability verdict, or null when the rule declares no
90
96
  * applicability predicate and runs unconditionally.
91
97
  */
92
- export declare function evaluateRuleApplicability(ruleId: string, dataAccessConfig: Record<string, unknown> | undefined, ddlColumns: string[] | undefined): RuleApplicability | null;
98
+ export declare function evaluateRuleApplicability(ruleId: string, dataAccessConfig: Record<string, unknown> | undefined, ddlTableColumns: Record<string, string[]> | undefined): RuleApplicability | null;
93
99
  /**
94
100
  * Spec 44 bucket 2 — rules that are structurally unreachable: their predicate
95
101
  * reads a field no extractor populates (or they are a legacy alias with no
@@ -101,6 +107,23 @@ export declare function evaluateRuleApplicability(ruleId: string, dataAccessConf
101
107
  * Each reason names the specific extractor and the specific field (or absence
102
108
  * of an emission site) so a reader can tell *why* it cannot fire. Remove an id
103
109
  * here when its extraction begins emitting it.
110
+ *
111
+ * As of 4.1.0 this map is empty: the ten `cannot-fire` rules (the six
112
+ * api-contract rules, `file-error`, and the three schema-validator aliases)
113
+ * were removed outright — registry entry, emission site, and ledger row — rather
114
+ * than kept as standing findings. The `cannot-fire` verdict remains part of the
115
+ * applicability vocabulary for when a future rule is genuinely unreachable, but
116
+ * no such rule currently exists.
117
+ *
118
+ * This map is NOT the only producer of the `cannot-fire` state: the static-config
119
+ * extractors (`lintConfigReader.ts`, `tailwindConfigLoader.ts`, and the
120
+ * styles-source visitor in `pipelineAdapters.ts`) emit a `CoverageDiagnostic`
121
+ * with `kind: 'cannot-fire'` when a project config cannot be read statically
122
+ * (Spec 61 R3.4). That diagnostic route is independent of this map, so emptying
123
+ * this map does not dead the `cannot-fire` state — the diagnostic route remains
124
+ * live (and is exercised by `spec61-exploits.spec.ts` fixture 8). The
125
+ * unresolvable dynamic-import path emits the sibling `unresolved-dynamic-import`
126
+ * kind, not `cannot-fire`.
104
127
  */
105
128
  export declare const CANNOT_FIRE_RULES: ReadonlyMap<string, string>;
106
129
  //# sourceMappingURL=applicability.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"applicability.d.ts","sourceRoot":"","sources":["../../src/analyzers/applicability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,eAAe,GAAG,aAAa,CAAC;CACxC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,mBAAmB,EAAE,aAAa,CAAC,MAAM,CAMrD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,MAAM,GAChB,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAWhC;AAUD;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACrD,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,GAC/B,iBAAiB,GAAG,IAAI,CAS1B;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAiBxD,CAAC"}
1
+ {"version":3,"file":"applicability.d.ts","sourceRoot":"","sources":["../../src/analyzers/applicability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAQH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,eAAe,GAAG,aAAa,CAAC;CACxC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,mBAAmB,EAAE,aAAa,CAAC,MAAM,CAMrD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,MAAM,GAChB,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAWhC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACrD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,GACpD,iBAAiB,GAAG,IAAI,CAS1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAe,CAAC"}
@@ -13,7 +13,13 @@
13
13
  * UniversalSchemaAnalyzer.js → makeVisitorStatus), so a static analyzer import
14
14
  * here would create a pipeline↔analyzer cycle. The pipeline-side convention is
15
15
  * to reach analyzers only through dynamic import() (see pipelineAdapters.ts).
16
+ *
17
+ * The one exception is {@link orgFilterTiers}: a pure, dependency-free module
18
+ * that is the single source of truth for tenant-scoping tiers. Both this
19
+ * applicability predicate and the Stage-4 missing-org-filter reducer derive
20
+ * from it, so firing and applicability can never read different tier sets.
16
21
  */
22
+ import { buildOrgFilterTierSet, hasDeclaredTenancy, } from './orgFilterTiers.js';
17
23
  /**
18
24
  * Spec 52 R3 — the whole-program rule class. These rules draw a global
19
25
  * conclusion ("table X is never read", "table Y is unknown", "no validator is
@@ -70,13 +76,6 @@ export function scopedWholeProgramApplicability(isScoped, fileCount) {
70
76
  }
71
77
  return map;
72
78
  }
73
- /**
74
- * Default tenant-scoping column names. The single source of truth is
75
- * DEFAULT_DATA_ACCESS_CONFIG.orgFilterColumns in UniversalDataAccessAnalyzer.js;
76
- * this is a local copy because importing that module here would create the cycle
77
- * described above. Keep in sync with that constant.
78
- */
79
- const DEFAULT_ORG_FILTER_COLUMNS = ['org_id', 'tenant_id', 'organization_id', 'workspace_id'];
80
79
  /**
81
80
  * Evaluate whether a rule is applicable to the current codebase, given inputs
82
81
  * the pipeline has already computed.
@@ -87,13 +86,14 @@ const DEFAULT_ORG_FILTER_COLUMNS = ['org_id', 'tenant_id', 'organization_id', 'w
87
86
  *
88
87
  * @param ruleId The registry rule id.
89
88
  * @param dataAccessConfig The namespaced data-access config (may be undefined).
90
- * @param ddlColumns Aggregated DDL-declared columns from the schema reducer.
89
+ * @param ddlTableColumns Aggregated DDL-declared per-table columns from the
90
+ * schema reducer (`Record<table, columns>`), folded corpus-wide.
91
91
  * @returns The rule's applicability verdict, or null when the rule declares no
92
92
  * applicability predicate and runs unconditionally.
93
93
  */
94
- export function evaluateRuleApplicability(ruleId, dataAccessConfig, ddlColumns) {
94
+ export function evaluateRuleApplicability(ruleId, dataAccessConfig, ddlTableColumns) {
95
95
  if (ruleId === 'missing-org-filter') {
96
- return evaluateMissingOrgFilterApplicability(dataAccessConfig, ddlColumns);
96
+ return evaluateMissingOrgFilterApplicability(dataAccessConfig, ddlTableColumns);
97
97
  }
98
98
  const cannotFireReason = CANNOT_FIRE_RULES.get(ruleId);
99
99
  if (cannotFireReason !== undefined) {
@@ -112,50 +112,44 @@ export function evaluateRuleApplicability(ruleId, dataAccessConfig, ddlColumns)
112
112
  * Each reason names the specific extractor and the specific field (or absence
113
113
  * of an emission site) so a reader can tell *why* it cannot fire. Remove an id
114
114
  * here when its extraction begins emitting it.
115
+ *
116
+ * As of 4.1.0 this map is empty: the ten `cannot-fire` rules (the six
117
+ * api-contract rules, `file-error`, and the three schema-validator aliases)
118
+ * were removed outright — registry entry, emission site, and ledger row — rather
119
+ * than kept as standing findings. The `cannot-fire` verdict remains part of the
120
+ * applicability vocabulary for when a future rule is genuinely unreachable, but
121
+ * no such rule currently exists.
122
+ *
123
+ * This map is NOT the only producer of the `cannot-fire` state: the static-config
124
+ * extractors (`lintConfigReader.ts`, `tailwindConfigLoader.ts`, and the
125
+ * styles-source visitor in `pipelineAdapters.ts`) emit a `CoverageDiagnostic`
126
+ * with `kind: 'cannot-fire'` when a project config cannot be read statically
127
+ * (Spec 61 R3.4). That diagnostic route is independent of this map, so emptying
128
+ * this map does not dead the `cannot-fire` state — the diagnostic route remains
129
+ * live (and is exercised by `spec61-exploits.spec.ts` fixture 8). The
130
+ * unresolvable dynamic-import path emits the sibling `unresolved-dynamic-import`
131
+ * kind, not `cannot-fire`.
115
132
  */
116
- export const CANNOT_FIRE_RULES = new Map([
117
- // api-contract — reads response/auth metadata that extractEndpoints /
118
- // extractAPICalls never populate, or has no emission site at all.
119
- ['api-type-mismatch', 'cannot fire — extractEndpoints/extractAPICalls never populate responseSchema/expectedResponseType/deprecated, the fields this rule reads'],
120
- ['missing-endpoint', 'cannot fire — gated: extractMethodFrom*/extractPathFromGo derive method and URL from function names (name proxy), so any finding is fabricated'],
121
- ['api-extra-field', 'cannot fire — no emission site: the analyzer has no code that produces this rule'],
122
- ['api-missing-field', 'cannot fire — no emission site: the analyzer has no code that produces this rule'],
123
- ['method-mismatch', 'cannot fire — gated: extractMethodFrom* derives the verb from function names (name proxy), so any finding is fabricated'],
124
- ['auth-mismatch', 'cannot fire — extractEndpoints never sets `authentication`, the field this rule reads'],
125
- // schema — file errors are routed to state.errors, never a file-error violation.
126
- ['file-error', 'cannot fire — schema file errors are routed to state.errors, never emitted as a `file-error` violation'],
127
- // schema-validator — legacy alias or reads constraints/version the extractor never assigns.
128
- ['field-mismatch', 'cannot fire — legacy alias: the validator emits `schema-field-mismatch`, never `field-mismatch`'],
129
- ['constraint-mismatch', 'cannot fire — extractSchemas never assigns `constraints` on fields, the input this rule reads'],
130
- ['version-mismatch', 'cannot fire — extractSchemas never assigns `version` on schemas, the input this rule reads'],
131
- ]);
133
+ export const CANNOT_FIRE_RULES = new Map([]);
132
134
  /**
133
- * Spec 39/42 R3 — `missing-org-filter` is applicable when the project declares a
134
- * tenant-scoping column in one of three places: configured tenant tables by name,
135
- * a configured schema table, or the DDL-derived table catalog.
135
+ * Spec 39/42 R3 + Spec 62 Amendment B — `missing-org-filter` is applicable when
136
+ * the project declares tenancy in any tier. Applicability and firing read the
137
+ * SAME tier set, built once by {@link buildOrgFilterTierSet}:
138
+ *
139
+ * Tier 1 (config-primary) — `orgFilterTables`, the explicit tenant-table list.
140
+ * Tier 2 (schema-inference) — a configured schema table carrying a
141
+ * tenant-scoping column (org_id/tenant_id/organization_id/workspace_id).
142
+ * Tier 3 (DDL-discovery) — a table whose DDL columns carry a tenant-scoping
143
+ * column. This tier was the Amendment B defect: applicability read it (3
144
+ * tiers) while the firing predicate read only Tiers 1–2, so a DDL-declared
145
+ * multi-tenant codebase un-suppressed the rule without ever making it fire —
146
+ * reporting `clean` on a real leak. Both consumers now derive from one
147
+ * function, so they cannot drift.
136
148
  */
137
- function evaluateMissingOrgFilterApplicability(dataAccessConfig, ddlColumns) {
138
- // Tier 1 — user declared tenant-scoped tables by name (policy of record).
139
- const orgFilterTables = dataAccessConfig?.orgFilterTables ?? [];
140
- if (orgFilterTables.length > 0)
141
- return { applicable: true };
142
- const orgFilterColumns = dataAccessConfig?.orgFilterColumns ?? DEFAULT_ORG_FILTER_COLUMNS;
143
- const schemas = dataAccessConfig?.schemas ?? [];
144
- const tenantColumns = new Set(orgFilterColumns.map((c) => String(c).toLowerCase()));
145
- // Tier 2 — a configured schema declares a table carrying a tenant-scoping column.
146
- for (const schema of schemas) {
147
- for (const table of schema.tables ?? []) {
148
- for (const column of table.columns ?? []) {
149
- if (tenantColumns.has(String(column.name).toLowerCase())) {
150
- return { applicable: true };
151
- }
152
- }
153
- }
154
- }
155
- // Tier 3 — the table catalog (DDL-derived columns) carries a tenant-scoping column.
156
- if (ddlColumns?.some((c) => tenantColumns.has(String(c).toLowerCase()))) {
149
+ function evaluateMissingOrgFilterApplicability(dataAccessConfig, ddlTableColumns) {
150
+ const tierSet = buildOrgFilterTierSet(dataAccessConfig, ddlTableColumns);
151
+ if (hasDeclaredTenancy(tierSet))
157
152
  return { applicable: true };
158
- }
159
153
  return {
160
154
  applicable: false,
161
155
  reason: 'no tenant-scoping column found in table catalog',
@@ -1 +1 @@
1
- {"version":3,"file":"applicability.js","sourceRoot":"","sources":["../../src/analyzers/applicability.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"applicability.js","sourceRoot":"","sources":["../../src/analyzers/applicability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EACL,qBAAqB,EACrB,kBAAkB,GAEnB,MAAM,qBAAqB,CAAC;AAe7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA0B;IACxD,iCAAiC;IACjC,iCAAiC;IACjC,qCAAqC;IACrC,eAAe;IACf,uBAAuB;CACxB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,+BAA+B,CAC7C,QAAiB,EACjB,SAAiB;IAEjB,MAAM,GAAG,GAAG,IAAI,GAAG,EAA6B,CAAC;IACjD,IAAI,CAAC,QAAQ;QAAE,OAAO,GAAG,CAAC;IAC1B,KAAK,MAAM,MAAM,IAAI,mBAAmB,EAAE,CAAC;QACzC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE;YACd,UAAU,EAAE,KAAK;YACjB,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,2DAA2D,SAAS,UAAU;SACvF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAcD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAAc,EACd,gBAAqD,EACrD,eAAqD;IAErD,IAAI,MAAM,KAAK,oBAAoB,EAAE,CAAC;QACpC,OAAO,qCAAqC,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvD,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IAC9E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAgC,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC;AAE1E;;;;;;;;;;;;;;GAcG;AACH,SAAS,qCAAqC,CAC5C,gBAAqD,EACrD,eAAqD;IAErD,MAAM,OAAO,GAAG,qBAAqB,CAAC,gBAA+C,EAAE,eAAe,CAAC,CAAC;IACxG,IAAI,kBAAkB,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IAE7D,OAAO;QACL,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,iDAAiD;KAC1D,CAAC;AACJ,CAAC"}
@@ -28,61 +28,30 @@ export interface APICall {
28
28
  errorHandling?: string[];
29
29
  timeout?: number;
30
30
  }
31
- export interface ContractViolation extends Violation {
32
- rule: 'api-type-mismatch' | 'missing-endpoint' | 'api-extra-field' | 'api-missing-field' | 'method-mismatch' | 'auth-mismatch';
33
- contractType: 'api-type-mismatch' | 'missing-endpoint' | 'api-extra-field' | 'api-missing-field' | 'method-mismatch' | 'auth-mismatch';
34
- endpoint?: APIEndpoint;
35
- call?: APICall;
36
- expectedType?: string;
37
- actualType?: string;
38
- missingFields?: string[];
39
- extraFields?: string[];
40
- }
41
31
  /**
42
32
  * Api contract analyzer.
33
+ *
34
+ * All six api-contract rules were removed in 4.1.0: each was `cannot-fire` (its
35
+ * extractor never populated the fields it read, or its computation was a name
36
+ * proxy). The rules were removed outright rather than kept as standing findings,
37
+ * so this analyzer is a no-op that returns no violations. The endpoint/call
38
+ * extraction below remains for when real contract extraction lands.
43
39
  */
44
40
  export declare class APIContractAnalyzer {
45
- private endpoints;
46
- private calls;
47
- /**
48
- * Analyze API contracts and find violations
49
- * @param calls
50
- * @param endpoints
51
- * @returns
52
- */
53
- analyzeContracts(endpoints: APIEndpoint[], calls: APICall[]): Promise<ContractViolation[]>;
54
- /**
55
- * Find API calls that don't have matching endpoints
56
- */
57
- private findUnmatchedCalls;
58
- /**
59
- * Validate matched endpoint-call pairs for compatibility
60
- */
61
- private validateMatchedPairs;
62
- /**
63
- * Check for usage of deprecated APIs
64
- */
65
- private checkDeprecatedUsage;
66
- /**
67
- * Validate authentication requirements
68
- */
69
- private validateAuthentication;
70
- /**
71
- * Find matching endpoint for an API call
72
- */
73
- private findMatchingEndpoint;
74
- /**
75
- * Check if two API paths match (handling path parameters)
76
- */
77
- private pathsMatch;
78
- /**
79
- * Validate type compatibility between endpoint and call
80
- */
81
- private validateTypeCompatibility;
82
41
  /**
83
- * Check if an API call includes authentication
42
+ * Detect mismatches between a project's declared API endpoints and the calls
43
+ * its clients make against them.
44
+ *
45
+ * A no-op as of 4.1.0: all six api-contract rules this method fed were removed
46
+ * (each was `cannot-fire`), so it always returns an empty list. Kept as the
47
+ * seam real contract extraction will plug into — the endpoint/call extraction
48
+ * below remains for that work.
49
+ *
50
+ * @param _endpoints The API endpoints extracted from the corpus.
51
+ * @param _calls The API calls extracted from the corpus.
52
+ * @returns An empty list (no contract rules are live).
84
53
  */
85
- private callHasAuthentication;
54
+ analyzeContracts(_endpoints: APIEndpoint[], _calls: APICall[]): Promise<Violation[]>;
86
55
  }
87
56
  /**
88
57
  * Extract API endpoints from code entities
@@ -1 +1 @@
1
- {"version":3,"file":"APIContractAnalyzer.d.ts","sourceRoot":"","sources":["../../../src/analyzers/cross-language/APIContractAnalyzer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA+B,UAAU,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACpG,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,cAAc,CAAC,EAAE,UAAU,CAAC;IAC5B,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IAClD,IAAI,EAAE,mBAAmB,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,eAAe,CAAC;IAC/H,YAAY,EAAE,mBAAmB,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,eAAe,CAAC;IACvI,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,KAAK,CAAiB;IAE9B;;;;;OAKG;IACG,gBAAgB,CACpB,SAAS,EAAE,WAAW,EAAE,EACxB,KAAK,EAAE,OAAO,EAAE,GACf,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAqB/B;;OAEG;YACW,kBAAkB;IA6BhC;;OAEG;YACW,oBAAoB;IA2ClC;;OAEG;YACW,oBAAoB;IA6BlC;;OAEG;YACW,sBAAsB;IA+BpC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAa5B;;OAEG;IACH,OAAO,CAAC,UAAU;IA6BlB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAkCjC;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAM9B;AAwBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,WAAW,EAAE,CAwB/D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAkB1D"}
1
+ {"version":3,"file":"APIContractAnalyzer.d.ts","sourceRoot":"","sources":["../../../src/analyzers/cross-language/APIContractAnalyzer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,cAAc,CAAC,EAAE,UAAU,CAAC;IAC5B,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;IAC9B;;;;;;;;;;;;OAYG;IACG,gBAAgB,CACpB,UAAU,EAAE,WAAW,EAAE,EACzB,MAAM,EAAE,OAAO,EAAE,GAChB,OAAO,CAAC,SAAS,EAAE,CAAC;CAGxB;AAUD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,WAAW,EAAE,CAwB/D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAkB1D"}