auditor-lambda 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/README.md +173 -0
  2. package/audit-code-wrapper-lib.mjs +905 -0
  3. package/audit-code.mjs +13 -0
  4. package/dist/adapters/coverageSummary.d.ts +8 -0
  5. package/dist/adapters/coverageSummary.js +13 -0
  6. package/dist/adapters/eslint.d.ts +13 -0
  7. package/dist/adapters/eslint.js +21 -0
  8. package/dist/adapters/normalizeExternal.d.ts +12 -0
  9. package/dist/adapters/normalizeExternal.js +19 -0
  10. package/dist/adapters/npmAudit.d.ts +15 -0
  11. package/dist/adapters/npmAudit.js +12 -0
  12. package/dist/adapters/semgrep.d.ts +22 -0
  13. package/dist/adapters/semgrep.js +14 -0
  14. package/dist/cli.d.ts +1 -0
  15. package/dist/cli.js +724 -0
  16. package/dist/coverage.d.ts +11 -0
  17. package/dist/coverage.js +102 -0
  18. package/dist/extractors/bucketing.d.ts +7 -0
  19. package/dist/extractors/bucketing.js +72 -0
  20. package/dist/extractors/disposition.d.ts +4 -0
  21. package/dist/extractors/disposition.js +41 -0
  22. package/dist/extractors/fileInventory.d.ts +7 -0
  23. package/dist/extractors/fileInventory.js +44 -0
  24. package/dist/extractors/flows.d.ts +5 -0
  25. package/dist/extractors/flows.js +125 -0
  26. package/dist/extractors/fsIntake.d.ts +8 -0
  27. package/dist/extractors/fsIntake.js +66 -0
  28. package/dist/extractors/graph.d.ts +4 -0
  29. package/dist/extractors/graph.js +46 -0
  30. package/dist/extractors/ignore.d.ts +1 -0
  31. package/dist/extractors/ignore.js +17 -0
  32. package/dist/extractors/risk.d.ts +5 -0
  33. package/dist/extractors/risk.js +45 -0
  34. package/dist/extractors/surfaces.d.ts +4 -0
  35. package/dist/extractors/surfaces.js +40 -0
  36. package/dist/index.d.ts +1 -0
  37. package/dist/index.js +1 -0
  38. package/dist/io/artifacts.d.ts +38 -0
  39. package/dist/io/artifacts.js +100 -0
  40. package/dist/io/json.d.ts +8 -0
  41. package/dist/io/json.js +96 -0
  42. package/dist/io/runArtifacts.d.ts +14 -0
  43. package/dist/io/runArtifacts.js +37 -0
  44. package/dist/orchestrator/advance.d.ts +24 -0
  45. package/dist/orchestrator/advance.js +104 -0
  46. package/dist/orchestrator/artifactMetadata.d.ts +4 -0
  47. package/dist/orchestrator/artifactMetadata.js +111 -0
  48. package/dist/orchestrator/autoFixExecutor.d.ts +3 -0
  49. package/dist/orchestrator/autoFixExecutor.js +63 -0
  50. package/dist/orchestrator/chunking.d.ts +5 -0
  51. package/dist/orchestrator/chunking.js +13 -0
  52. package/dist/orchestrator/dependencyMap.d.ts +1 -0
  53. package/dist/orchestrator/dependencyMap.js +82 -0
  54. package/dist/orchestrator/executors.d.ts +6 -0
  55. package/dist/orchestrator/executors.js +52 -0
  56. package/dist/orchestrator/flowCoverage.d.ts +4 -0
  57. package/dist/orchestrator/flowCoverage.js +44 -0
  58. package/dist/orchestrator/flowPlanning.d.ts +3 -0
  59. package/dist/orchestrator/flowPlanning.js +42 -0
  60. package/dist/orchestrator/flowRequeue.d.ts +5 -0
  61. package/dist/orchestrator/flowRequeue.js +58 -0
  62. package/dist/orchestrator/internalExecutors.d.ts +16 -0
  63. package/dist/orchestrator/internalExecutors.js +212 -0
  64. package/dist/orchestrator/nextStep.d.ts +9 -0
  65. package/dist/orchestrator/nextStep.js +44 -0
  66. package/dist/orchestrator/planning.d.ts +4 -0
  67. package/dist/orchestrator/planning.js +62 -0
  68. package/dist/orchestrator/requeue.d.ts +3 -0
  69. package/dist/orchestrator/requeue.js +25 -0
  70. package/dist/orchestrator/requeueCommand.d.ts +10 -0
  71. package/dist/orchestrator/requeueCommand.js +27 -0
  72. package/dist/orchestrator/resultIngestion.d.ts +2 -0
  73. package/dist/orchestrator/resultIngestion.js +13 -0
  74. package/dist/orchestrator/runtimeValidation.d.ts +7 -0
  75. package/dist/orchestrator/runtimeValidation.js +103 -0
  76. package/dist/orchestrator/runtimeValidationUpdate.d.ts +2 -0
  77. package/dist/orchestrator/runtimeValidationUpdate.js +52 -0
  78. package/dist/orchestrator/staleness.d.ts +2 -0
  79. package/dist/orchestrator/staleness.js +83 -0
  80. package/dist/orchestrator/state.d.ts +3 -0
  81. package/dist/orchestrator/state.js +85 -0
  82. package/dist/orchestrator/syntaxResolutionExecutor.d.ts +3 -0
  83. package/dist/orchestrator/syntaxResolutionExecutor.js +99 -0
  84. package/dist/orchestrator/taskBuilder.d.ts +12 -0
  85. package/dist/orchestrator/taskBuilder.js +154 -0
  86. package/dist/orchestrator/unitBuilder.d.ts +3 -0
  87. package/dist/orchestrator/unitBuilder.js +145 -0
  88. package/dist/orchestrator.d.ts +6 -0
  89. package/dist/orchestrator.js +33 -0
  90. package/dist/prompts/renderWorkerPrompt.d.ts +2 -0
  91. package/dist/prompts/renderWorkerPrompt.js +19 -0
  92. package/dist/providers/claudeCodeProvider.d.ts +8 -0
  93. package/dist/providers/claudeCodeProvider.js +20 -0
  94. package/dist/providers/index.d.ts +7 -0
  95. package/dist/providers/index.js +77 -0
  96. package/dist/providers/localSubprocessProvider.d.ts +5 -0
  97. package/dist/providers/localSubprocessProvider.js +13 -0
  98. package/dist/providers/opencodeProvider.d.ts +8 -0
  99. package/dist/providers/opencodeProvider.js +15 -0
  100. package/dist/providers/spawnLoggedCommand.d.ts +2 -0
  101. package/dist/providers/spawnLoggedCommand.js +48 -0
  102. package/dist/providers/subprocessTemplateProvider.d.ts +8 -0
  103. package/dist/providers/subprocessTemplateProvider.js +41 -0
  104. package/dist/providers/types.d.ts +22 -0
  105. package/dist/providers/types.js +1 -0
  106. package/dist/providers/vscodeTaskProvider.d.ts +8 -0
  107. package/dist/providers/vscodeTaskProvider.js +14 -0
  108. package/dist/reporting/mergeFindings.d.ts +4 -0
  109. package/dist/reporting/mergeFindings.js +136 -0
  110. package/dist/reporting/rootCause.d.ts +11 -0
  111. package/dist/reporting/rootCause.js +69 -0
  112. package/dist/reporting/synthesis.d.ts +21 -0
  113. package/dist/reporting/synthesis.js +55 -0
  114. package/dist/supervisor/operatorHandoff.d.ts +37 -0
  115. package/dist/supervisor/operatorHandoff.js +144 -0
  116. package/dist/supervisor/runLedger.d.ts +3 -0
  117. package/dist/supervisor/runLedger.js +17 -0
  118. package/dist/supervisor/sessionConfig.d.ts +4 -0
  119. package/dist/supervisor/sessionConfig.js +26 -0
  120. package/dist/types/artifactMetadata.d.ts +8 -0
  121. package/dist/types/artifactMetadata.js +1 -0
  122. package/dist/types/auditState.d.ts +14 -0
  123. package/dist/types/auditState.js +1 -0
  124. package/dist/types/disposition.d.ts +9 -0
  125. package/dist/types/disposition.js +1 -0
  126. package/dist/types/externalAnalyzer.d.ts +16 -0
  127. package/dist/types/externalAnalyzer.js +1 -0
  128. package/dist/types/flowCoverage.d.ts +11 -0
  129. package/dist/types/flowCoverage.js +1 -0
  130. package/dist/types/flows.d.ts +11 -0
  131. package/dist/types/flows.js +1 -0
  132. package/dist/types/graph.d.ts +18 -0
  133. package/dist/types/graph.js +1 -0
  134. package/dist/types/risk.d.ts +9 -0
  135. package/dist/types/risk.js +1 -0
  136. package/dist/types/runLedger.d.ts +13 -0
  137. package/dist/types/runLedger.js +1 -0
  138. package/dist/types/runtimeValidation.d.ts +22 -0
  139. package/dist/types/runtimeValidation.js +1 -0
  140. package/dist/types/sessionConfig.d.ts +27 -0
  141. package/dist/types/sessionConfig.js +1 -0
  142. package/dist/types/surfaces.d.ts +11 -0
  143. package/dist/types/surfaces.js +1 -0
  144. package/dist/types/workerResult.d.ts +13 -0
  145. package/dist/types/workerResult.js +1 -0
  146. package/dist/types/workerSession.d.ts +13 -0
  147. package/dist/types/workerSession.js +1 -0
  148. package/dist/types.d.ts +104 -0
  149. package/dist/types.js +1 -0
  150. package/dist/validation/artifacts.d.ts +3 -0
  151. package/dist/validation/artifacts.js +191 -0
  152. package/dist/validation/basic.d.ts +5 -0
  153. package/dist/validation/basic.js +9 -0
  154. package/dist/validation/sessionConfig.d.ts +6 -0
  155. package/dist/validation/sessionConfig.js +139 -0
  156. package/docs/agent-integrations.md +237 -0
  157. package/docs/agent-roles.md +69 -0
  158. package/docs/architecture.md +90 -0
  159. package/docs/artifacts.md +69 -0
  160. package/docs/bootstrap-install.md +79 -0
  161. package/docs/contract.md +140 -0
  162. package/docs/github-copilot.md +50 -0
  163. package/docs/model-selection.md +86 -0
  164. package/docs/next-steps.md +161 -0
  165. package/docs/packaging.md +88 -0
  166. package/docs/pipeline.md +152 -0
  167. package/docs/product-direction.md +111 -0
  168. package/docs/production-launch-bar.md +83 -0
  169. package/docs/production-readiness.md +52 -0
  170. package/docs/repo-layout.md +30 -0
  171. package/docs/run-flow.md +49 -0
  172. package/docs/session-config.md +232 -0
  173. package/docs/supervisor.md +83 -0
  174. package/docs/usage.md +172 -0
  175. package/docs/windows-setup.md +146 -0
  176. package/package.json +56 -0
  177. package/schemas/audit-code-v1alpha1.schema.json +191 -0
  178. package/schemas/audit_result.schema.json +48 -0
  179. package/schemas/audit_state.schema.json +36 -0
  180. package/schemas/audit_task.schema.json +49 -0
  181. package/schemas/blind_spot_register.schema.json +40 -0
  182. package/schemas/coverage_matrix.schema.json +50 -0
  183. package/schemas/critical_flows.schema.json +38 -0
  184. package/schemas/external_analyzer_results.schema.json +31 -0
  185. package/schemas/file_disposition.schema.json +33 -0
  186. package/schemas/finding.schema.json +62 -0
  187. package/schemas/flow_coverage.schema.json +44 -0
  188. package/schemas/graph_bundle.schema.json +55 -0
  189. package/schemas/merged_findings.schema.json +14 -0
  190. package/schemas/repo_manifest.schema.json +37 -0
  191. package/schemas/risk_register.schema.json +30 -0
  192. package/schemas/root_cause_clusters.schema.json +31 -0
  193. package/schemas/runtime_validation_report.schema.json +34 -0
  194. package/schemas/runtime_validation_tasks.schema.json +36 -0
  195. package/schemas/surface_manifest.schema.json +32 -0
  196. package/schemas/synthesis_report.schema.json +61 -0
  197. package/schemas/unit_manifest.schema.json +36 -0
  198. package/skills/audit-code/SKILL.md +54 -0
  199. package/skills/audit-code/audit-code.prompt.md +66 -0
@@ -0,0 +1,11 @@
1
+ import type { CoverageFileRecord, CoverageMatrix, Lens, ReviewedLineRange } from "./types.js";
2
+ export declare function mergeRanges(ranges: ReviewedLineRange[]): ReviewedLineRange[];
3
+ export declare function createCoverageMatrix(paths: string[]): CoverageMatrix;
4
+ export declare function markExcludedPath(matrix: CoverageMatrix, path: string, classificationStatus: string): void;
5
+ export declare function applyUnitCoverage(matrix: CoverageMatrix, path: string, unitId: string, requiredLenses: Lens[]): void;
6
+ export declare function applyReviewedRanges(matrix: CoverageMatrix, reviewedRanges: ReviewedLineRange[]): void;
7
+ export declare function findUncoveredFiles(matrix: CoverageMatrix): CoverageFileRecord[];
8
+ export declare function buildRequeueTargets(matrix: CoverageMatrix): Array<{
9
+ path: string;
10
+ missing_lenses: Lens[];
11
+ }>;
@@ -0,0 +1,102 @@
1
+ function sortRanges(ranges) {
2
+ return [...ranges].sort((a, b) => {
3
+ if (a.path !== b.path)
4
+ return a.path.localeCompare(b.path);
5
+ if (a.start !== b.start)
6
+ return a.start - b.start;
7
+ return a.end - b.end;
8
+ });
9
+ }
10
+ export function mergeRanges(ranges) {
11
+ const sorted = sortRanges(ranges);
12
+ const merged = [];
13
+ for (const range of sorted) {
14
+ const last = merged[merged.length - 1];
15
+ if (!last || last.path !== range.path || range.start > last.end + 1) {
16
+ merged.push({ ...range });
17
+ continue;
18
+ }
19
+ last.end = Math.max(last.end, range.end);
20
+ last.pass_id = `${last.pass_id},${range.pass_id}`;
21
+ last.agent_role = [last.agent_role, range.agent_role]
22
+ .filter(Boolean)
23
+ .join(",");
24
+ }
25
+ return merged;
26
+ }
27
+ export function createCoverageMatrix(paths) {
28
+ return {
29
+ files: paths.map((path) => ({
30
+ path,
31
+ unit_ids: [],
32
+ classification_status: "unclassified",
33
+ audit_status: "pending",
34
+ required_lenses: [],
35
+ completed_lenses: [],
36
+ reviewed_line_ranges: [],
37
+ })),
38
+ };
39
+ }
40
+ export function markExcludedPath(matrix, path, classificationStatus) {
41
+ const record = matrix.files.find((file) => file.path === path);
42
+ if (!record)
43
+ return;
44
+ record.classification_status = classificationStatus;
45
+ record.audit_status = "excluded";
46
+ record.required_lenses = [];
47
+ record.completed_lenses = [];
48
+ record.reviewed_line_ranges = [];
49
+ record.unit_ids = [];
50
+ }
51
+ export function applyUnitCoverage(matrix, path, unitId, requiredLenses) {
52
+ const record = matrix.files.find((file) => file.path === path);
53
+ if (!record || record.audit_status === "excluded")
54
+ return;
55
+ if (!record.unit_ids.includes(unitId)) {
56
+ record.unit_ids.push(unitId);
57
+ }
58
+ record.classification_status = "classified";
59
+ record.required_lenses = [
60
+ ...new Set([...record.required_lenses, ...requiredLenses]),
61
+ ];
62
+ }
63
+ export function applyReviewedRanges(matrix, reviewedRanges) {
64
+ for (const range of reviewedRanges) {
65
+ const record = matrix.files.find((file) => file.path === range.path);
66
+ if (!record || record.audit_status === "excluded")
67
+ continue;
68
+ record.reviewed_line_ranges.push(range);
69
+ record.reviewed_line_ranges = mergeRanges(record.reviewed_line_ranges);
70
+ if (range.lens && !record.completed_lenses.includes(range.lens)) {
71
+ record.completed_lenses.push(range.lens);
72
+ }
73
+ }
74
+ for (const file of matrix.files) {
75
+ const hasAllRequired = file.required_lenses.every((lens) => file.completed_lenses.includes(lens));
76
+ if (file.audit_status === "excluded") {
77
+ continue;
78
+ }
79
+ if (hasAllRequired && file.required_lenses.length > 0) {
80
+ file.audit_status = "complete";
81
+ }
82
+ else if (file.reviewed_line_ranges.length > 0) {
83
+ file.audit_status = "partial";
84
+ }
85
+ }
86
+ }
87
+ export function findUncoveredFiles(matrix) {
88
+ return matrix.files.filter((file) => {
89
+ if (file.audit_status === "excluded")
90
+ return false;
91
+ return file.audit_status !== "complete";
92
+ });
93
+ }
94
+ export function buildRequeueTargets(matrix) {
95
+ return matrix.files
96
+ .filter((file) => file.audit_status !== "excluded")
97
+ .map((file) => ({
98
+ path: file.path,
99
+ missing_lenses: file.required_lenses.filter((lens) => !file.completed_lenses.includes(lens)),
100
+ }))
101
+ .filter((item) => item.missing_lenses.length > 0);
102
+ }
@@ -0,0 +1,7 @@
1
+ export type FileBucket = "runtime" | "interface" | "data_layer" | "security_sensitive" | "concurrency_state" | "tests" | "tooling_scripts" | "config_deployment" | "docs_specs" | "generated_vendor" | "unknown";
2
+ export interface BucketAssignment {
3
+ path: string;
4
+ buckets: FileBucket[];
5
+ rationale: string[];
6
+ }
7
+ export declare function bucketFile(path: string): BucketAssignment;
@@ -0,0 +1,72 @@
1
+ function addBucket(buckets, rationale, bucket, reason) {
2
+ if (!buckets.has(bucket)) {
3
+ buckets.add(bucket);
4
+ rationale.push(reason);
5
+ }
6
+ }
7
+ export function bucketFile(path) {
8
+ const normalized = path.toLowerCase();
9
+ const buckets = new Set();
10
+ const rationale = [];
11
+ if (normalized.includes("test") ||
12
+ normalized.includes("spec") ||
13
+ normalized.includes("__tests__")) {
14
+ addBucket(buckets, rationale, "tests", "path suggests tests");
15
+ }
16
+ if (normalized.includes("route") ||
17
+ normalized.includes("controller") ||
18
+ normalized.includes("handler") ||
19
+ normalized.includes("api/")) {
20
+ addBucket(buckets, rationale, "interface", "path suggests interface code");
21
+ }
22
+ if (normalized.includes("model") ||
23
+ normalized.includes("schema") ||
24
+ normalized.includes("migration") ||
25
+ normalized.includes("seed") ||
26
+ normalized.includes("db/")) {
27
+ addBucket(buckets, rationale, "data_layer", "path suggests data-layer code");
28
+ }
29
+ if (normalized.includes("auth") ||
30
+ normalized.includes("secret") ||
31
+ normalized.includes("token") ||
32
+ normalized.includes("permission") ||
33
+ normalized.includes("session")) {
34
+ addBucket(buckets, rationale, "security_sensitive", "path suggests security-sensitive code");
35
+ }
36
+ if (normalized.includes("queue") ||
37
+ normalized.includes("worker") ||
38
+ normalized.includes("job") ||
39
+ normalized.includes("cache") ||
40
+ normalized.includes("retry") ||
41
+ normalized.includes("lock")) {
42
+ addBucket(buckets, rationale, "concurrency_state", "path suggests concurrency or stateful behavior");
43
+ }
44
+ if (normalized.includes("script") ||
45
+ normalized.startsWith("scripts/") ||
46
+ normalized.startsWith("bin/")) {
47
+ addBucket(buckets, rationale, "tooling_scripts", "path suggests tooling or scripts");
48
+ }
49
+ if (normalized.includes("docker") ||
50
+ normalized.includes("terraform") ||
51
+ normalized.includes("deploy") ||
52
+ normalized.includes("workflow") ||
53
+ normalized.includes("k8s") ||
54
+ normalized.endsWith(".yml") ||
55
+ normalized.endsWith(".yaml")) {
56
+ addBucket(buckets, rationale, "config_deployment", "path suggests config or deployment artifact");
57
+ }
58
+ if (normalized.endsWith(".md") || normalized.startsWith("docs/")) {
59
+ addBucket(buckets, rationale, "docs_specs", "path suggests documentation");
60
+ }
61
+ if (normalized.includes("vendor") || normalized.includes("generated")) {
62
+ addBucket(buckets, rationale, "generated_vendor", "path suggests generated or vendored content");
63
+ }
64
+ if (buckets.size === 0) {
65
+ addBucket(buckets, rationale, "runtime", "default runtime classification");
66
+ }
67
+ return {
68
+ path,
69
+ buckets: [...buckets],
70
+ rationale,
71
+ };
72
+ }
@@ -0,0 +1,4 @@
1
+ import type { RepoManifest } from "../types.js";
2
+ import type { FileDisposition, FileDispositionStatus } from "../types/disposition.js";
3
+ export declare function buildFileDisposition(repoManifest: RepoManifest): FileDisposition;
4
+ export declare function isAuditExcludedStatus(status: FileDispositionStatus): boolean;
@@ -0,0 +1,41 @@
1
+ function inferDisposition(path) {
2
+ const normalized = path.toLowerCase();
3
+ if (normalized.startsWith("dist/") || normalized.startsWith("build/")) {
4
+ return { path, status: "generated", reason: "Build output path." };
5
+ }
6
+ if (normalized.includes("vendor") || normalized.includes("third_party")) {
7
+ return { path, status: "vendor", reason: "Vendor or third-party path." };
8
+ }
9
+ if (normalized.endsWith(".png") ||
10
+ normalized.endsWith(".jpg") ||
11
+ normalized.endsWith(".jpeg") ||
12
+ normalized.endsWith(".gif") ||
13
+ normalized.endsWith(".pdf") ||
14
+ normalized.endsWith(".zip")) {
15
+ return {
16
+ path,
17
+ status: "binary",
18
+ reason: "Non-source binary-like artifact.",
19
+ };
20
+ }
21
+ if (normalized.endsWith(".md") || normalized.startsWith("docs/")) {
22
+ return { path, status: "doc_only", reason: "Documentation artifact." };
23
+ }
24
+ return {
25
+ path,
26
+ status: "included",
27
+ reason: "Default included source or config artifact.",
28
+ };
29
+ }
30
+ export function buildFileDisposition(repoManifest) {
31
+ return {
32
+ files: repoManifest.files.map((file) => inferDisposition(file.path)),
33
+ };
34
+ }
35
+ export function isAuditExcludedStatus(status) {
36
+ return (status === "excluded" ||
37
+ status === "generated" ||
38
+ status === "vendor" ||
39
+ status === "binary" ||
40
+ status === "doc_only");
41
+ }
@@ -0,0 +1,7 @@
1
+ import type { RepoManifest } from "../types.js";
2
+ export interface InventoryInputFile {
3
+ path: string;
4
+ size_bytes: number;
5
+ hash?: string;
6
+ }
7
+ export declare function buildRepoManifest(repositoryName: string, files: InventoryInputFile[]): RepoManifest;
@@ -0,0 +1,44 @@
1
+ function inferLanguage(path) {
2
+ const ext = path.split(".").pop()?.toLowerCase();
3
+ switch (ext) {
4
+ case "ts":
5
+ case "tsx":
6
+ return "typescript";
7
+ case "js":
8
+ case "jsx":
9
+ return "javascript";
10
+ case "py":
11
+ return "python";
12
+ case "go":
13
+ return "go";
14
+ case "rs":
15
+ return "rust";
16
+ case "java":
17
+ return "java";
18
+ case "cs":
19
+ return "csharp";
20
+ case "json":
21
+ return "json";
22
+ case "yml":
23
+ case "yaml":
24
+ return "yaml";
25
+ case "md":
26
+ return "markdown";
27
+ default:
28
+ return "unknown";
29
+ }
30
+ }
31
+ export function buildRepoManifest(repositoryName, files) {
32
+ return {
33
+ repository: {
34
+ name: repositoryName,
35
+ },
36
+ generated_at: new Date().toISOString(),
37
+ files: files.map((file) => ({
38
+ path: file.path,
39
+ language: inferLanguage(file.path),
40
+ size_bytes: file.size_bytes,
41
+ hash: file.hash,
42
+ })),
43
+ };
44
+ }
@@ -0,0 +1,5 @@
1
+ import type { RepoManifest } from "../types.js";
2
+ import type { FileDisposition } from "../types/disposition.js";
3
+ import type { CriticalFlowManifest } from "../types/flows.js";
4
+ import type { SurfaceManifest } from "../types/surfaces.js";
5
+ export declare function buildCriticalFlowManifest(repoManifest: RepoManifest, surfaceManifest: SurfaceManifest, disposition?: FileDisposition): CriticalFlowManifest;
@@ -0,0 +1,125 @@
1
+ import { isAuditExcludedStatus } from "./disposition.js";
2
+ function inferConcerns(paths) {
3
+ const concerns = new Set();
4
+ for (const path of paths) {
5
+ const normalized = path.toLowerCase();
6
+ if (normalized.includes("auth") ||
7
+ normalized.includes("token") ||
8
+ normalized.includes("session"))
9
+ concerns.add("security");
10
+ if (normalized.includes("db") ||
11
+ normalized.includes("model") ||
12
+ normalized.includes("schema") ||
13
+ normalized.includes("migration") ||
14
+ normalized.includes("invoice") ||
15
+ normalized.includes("payment"))
16
+ concerns.add("data_integrity");
17
+ if (normalized.includes("worker") ||
18
+ normalized.includes("job") ||
19
+ normalized.includes("retry") ||
20
+ normalized.includes("queue"))
21
+ concerns.add("reliability");
22
+ if (normalized.includes("api") ||
23
+ normalized.includes("route") ||
24
+ normalized.includes("controller"))
25
+ concerns.add("correctness");
26
+ }
27
+ return concerns.size > 0 ? [...concerns] : ["correctness"];
28
+ }
29
+ function relatedPaths(entry, availablePaths) {
30
+ const normalized = entry.toLowerCase();
31
+ const linked = new Set([entry]);
32
+ for (const path of availablePaths) {
33
+ const lower = path.toLowerCase();
34
+ if (path === entry)
35
+ continue;
36
+ if ((normalized.includes("auth") || normalized.includes("session")) &&
37
+ (lower.includes("auth") ||
38
+ lower.includes("session") ||
39
+ lower.includes("token") ||
40
+ lower.includes("user"))) {
41
+ linked.add(path);
42
+ }
43
+ if ((normalized.includes("billing") ||
44
+ normalized.includes("invoice") ||
45
+ normalized.includes("payment")) &&
46
+ (lower.includes("billing") ||
47
+ lower.includes("invoice") ||
48
+ lower.includes("payment") ||
49
+ lower.includes("ledger") ||
50
+ lower.includes("subscription"))) {
51
+ linked.add(path);
52
+ }
53
+ if ((normalized.includes("job") ||
54
+ normalized.includes("worker") ||
55
+ normalized.includes("queue")) &&
56
+ (lower.includes("queue") ||
57
+ lower.includes("retry") ||
58
+ lower.includes("worker") ||
59
+ lower.includes("job") ||
60
+ lower.includes("task"))) {
61
+ linked.add(path);
62
+ }
63
+ if ((normalized.includes("deploy") || normalized.includes("docker")) &&
64
+ (lower.includes("deploy") ||
65
+ lower.includes("docker") ||
66
+ lower.includes("workflow") ||
67
+ lower.includes("k8s") ||
68
+ lower.includes("terraform"))) {
69
+ linked.add(path);
70
+ }
71
+ }
72
+ return [...linked].sort((a, b) => a.localeCompare(b));
73
+ }
74
+ function dedupeFlows(flows) {
75
+ const seen = new Set();
76
+ const deduped = [];
77
+ for (const flow of flows) {
78
+ const signature = `${flow.name}|${flow.paths.join(",")}|${flow.concerns.join(",")}`;
79
+ if (seen.has(signature))
80
+ continue;
81
+ seen.add(signature);
82
+ deduped.push(flow);
83
+ }
84
+ return deduped;
85
+ }
86
+ export function buildCriticalFlowManifest(repoManifest, surfaceManifest, disposition) {
87
+ const dispositionMap = new Map(disposition?.files.map((item) => [item.path, item.status]) ?? []);
88
+ const availablePaths = repoManifest.files
89
+ .map((file) => file.path)
90
+ .filter((path) => {
91
+ const status = dispositionMap.get(path);
92
+ return !(status && isAuditExcludedStatus(status));
93
+ });
94
+ const flows = [];
95
+ for (const surface of surfaceManifest.surfaces) {
96
+ const entry = surface.entrypoint;
97
+ const paths = relatedPaths(entry, availablePaths);
98
+ flows.push({
99
+ id: `flow:${surface.id.replace(/[^a-zA-Z0-9:_-]/g, "-")}`,
100
+ name: `${surface.kind} flow for ${entry}`,
101
+ entrypoints: [entry],
102
+ paths,
103
+ concerns: inferConcerns(paths),
104
+ notes: [
105
+ "Heuristic critical-flow inference from detected surfaces and related paths.",
106
+ ],
107
+ });
108
+ }
109
+ for (const path of availablePaths) {
110
+ const lower = path.toLowerCase();
111
+ if (lower.includes("migration") ||
112
+ lower.includes("schema") ||
113
+ lower.includes("seed")) {
114
+ flows.push({
115
+ id: `flow:data:${path.replace(/[^a-zA-Z0-9:_-]/g, "-")}`,
116
+ name: `data evolution flow for ${path}`,
117
+ entrypoints: [path],
118
+ paths: relatedPaths(path, availablePaths),
119
+ concerns: ["data_integrity", "reliability"],
120
+ notes: ["Heuristic data-evolution flow."],
121
+ });
122
+ }
123
+ }
124
+ return { flows: dedupeFlows(flows) };
125
+ }
@@ -0,0 +1,8 @@
1
+ import type { RepoManifest } from "../types.js";
2
+ export interface IntakeOptions {
3
+ root: string;
4
+ ignore?: string[];
5
+ hash_files?: boolean;
6
+ max_file_size_bytes?: number;
7
+ }
8
+ export declare function buildRepoManifestFromFs(options: IntakeOptions): Promise<RepoManifest>;
@@ -0,0 +1,66 @@
1
+ import { readdir, readFile, stat } from "node:fs/promises";
2
+ import { createHash } from "node:crypto";
3
+ import { join, relative, resolve } from "node:path";
4
+ import { buildRepoManifest } from "./fileInventory.js";
5
+ const DEFAULT_IGNORES = [
6
+ ".git",
7
+ "node_modules",
8
+ "dist",
9
+ "build",
10
+ ".next",
11
+ ".turbo",
12
+ ".artifacts",
13
+ ".audit-artifacts",
14
+ ".agent",
15
+ ".claude",
16
+ "coverage",
17
+ ];
18
+ function normalizePath(path) {
19
+ return path.replaceAll("\\", "/");
20
+ }
21
+ function shouldIgnore(relativePath, ignores) {
22
+ const normalized = normalizePath(relativePath);
23
+ return ignores.some((ignore) => {
24
+ const value = normalizePath(ignore);
25
+ return normalized === value || normalized.startsWith(`${value}/`);
26
+ });
27
+ }
28
+ async function maybeHashFile(path, enabled) {
29
+ if (!enabled)
30
+ return undefined;
31
+ const content = await readFile(path);
32
+ return createHash("sha256").update(content).digest("hex");
33
+ }
34
+ async function walk(root, current, ignores, hashFiles, maxFileSizeBytes, results) {
35
+ const entries = await readdir(current, { withFileTypes: true });
36
+ for (const entry of entries) {
37
+ const absolutePath = join(current, entry.name);
38
+ const relativePath = normalizePath(relative(root, absolutePath));
39
+ if (!relativePath || shouldIgnore(relativePath, ignores)) {
40
+ continue;
41
+ }
42
+ if (entry.isDirectory()) {
43
+ await walk(root, absolutePath, ignores, hashFiles, maxFileSizeBytes, results);
44
+ continue;
45
+ }
46
+ if (!entry.isFile()) {
47
+ continue;
48
+ }
49
+ const info = await stat(absolutePath);
50
+ const hash = info.size <= maxFileSizeBytes
51
+ ? await maybeHashFile(absolutePath, hashFiles)
52
+ : undefined;
53
+ results.push({
54
+ path: relativePath,
55
+ size_bytes: info.size,
56
+ hash,
57
+ });
58
+ }
59
+ }
60
+ export async function buildRepoManifestFromFs(options) {
61
+ const root = resolve(options.root);
62
+ const ignore = [...DEFAULT_IGNORES, ...(options.ignore ?? [])];
63
+ const files = [];
64
+ await walk(root, root, ignore, options.hash_files ?? false, options.max_file_size_bytes ?? 1024 * 1024, files);
65
+ return buildRepoManifest(root.split(/[\\/]/).pop() ?? "repo", files);
66
+ }
@@ -0,0 +1,4 @@
1
+ import type { RepoManifest } from "../types.js";
2
+ import type { FileDisposition } from "../types/disposition.js";
3
+ import type { GraphBundle } from "../types/graph.js";
4
+ export declare function buildGraphBundle(repoManifest: RepoManifest, disposition?: FileDisposition): GraphBundle;
@@ -0,0 +1,46 @@
1
+ import { isAuditExcludedStatus } from "./disposition.js";
2
+ export function buildGraphBundle(repoManifest, disposition) {
3
+ const imports = [];
4
+ const routes = [];
5
+ const dispositionMap = new Map(disposition?.files.map((item) => [item.path, item.status]) ?? []);
6
+ for (const file of repoManifest.files) {
7
+ const status = dispositionMap.get(file.path);
8
+ if (status && isAuditExcludedStatus(status)) {
9
+ continue;
10
+ }
11
+ const normalized = file.path.toLowerCase();
12
+ if (normalized.includes("api/") || normalized.includes("route")) {
13
+ routes.push({
14
+ path: `/${file.path.replaceAll("/", "_")}`,
15
+ handler: file.path,
16
+ method: "GET",
17
+ });
18
+ }
19
+ const parts = file.path.split("/");
20
+ if (parts.length > 2) {
21
+ imports.push({
22
+ from: file.path,
23
+ to: `${parts[0]}/${parts[1]}`,
24
+ kind: "heuristic-container-edge",
25
+ });
26
+ }
27
+ if (normalized.includes("auth") &&
28
+ normalized.includes("session") === false) {
29
+ for (const other of repoManifest.files) {
30
+ if (other.path === file.path)
31
+ continue;
32
+ const otherStatus = dispositionMap.get(other.path);
33
+ if (otherStatus && isAuditExcludedStatus(otherStatus))
34
+ continue;
35
+ if (other.path.toLowerCase().includes("session")) {
36
+ imports.push({
37
+ from: file.path,
38
+ to: other.path,
39
+ kind: "heuristic-auth-session-link",
40
+ });
41
+ }
42
+ }
43
+ }
44
+ }
45
+ return { graphs: { imports, routes } };
46
+ }
@@ -0,0 +1 @@
1
+ export declare function loadIgnoreFile(root: string, fileName?: string): Promise<string[]>;
@@ -0,0 +1,17 @@
1
+ import { access, readFile } from "node:fs/promises";
2
+ import { constants } from "node:fs";
3
+ import { join } from "node:path";
4
+ export async function loadIgnoreFile(root, fileName = ".auditorignore") {
5
+ const path = join(root, fileName);
6
+ try {
7
+ await access(path, constants.F_OK);
8
+ }
9
+ catch {
10
+ return [];
11
+ }
12
+ const content = await readFile(path, "utf8");
13
+ return content
14
+ .split(/\r?\n/)
15
+ .map((line) => line.trim())
16
+ .filter((line) => line.length > 0 && !line.startsWith("#"));
17
+ }
@@ -0,0 +1,5 @@
1
+ import type { UnitManifest } from "../types.js";
2
+ import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
3
+ import type { CriticalFlowManifest } from "../types/flows.js";
4
+ import type { RiskRegister } from "../types/risk.js";
5
+ export declare function buildRiskRegister(unitManifest: UnitManifest, criticalFlows?: CriticalFlowManifest, externalAnalyzerResults?: ExternalAnalyzerResults): RiskRegister;
@@ -0,0 +1,45 @@
1
+ export function buildRiskRegister(unitManifest, criticalFlows, externalAnalyzerResults) {
2
+ const flowMap = new Map();
3
+ for (const flow of criticalFlows?.flows ?? []) {
4
+ for (const path of flow.paths) {
5
+ flowMap.set(path, (flowMap.get(path) ?? 0) + 1);
6
+ }
7
+ }
8
+ const externalByPath = new Map();
9
+ for (const item of externalAnalyzerResults?.results ?? []) {
10
+ externalByPath.set(item.path, (externalByPath.get(item.path) ?? 0) + 1);
11
+ }
12
+ const items = unitManifest.units.map((unit) => {
13
+ const signals = [];
14
+ if ((unit.risk_score ?? 0) >= 5)
15
+ signals.push("high_bucket_density");
16
+ if (unit.required_lenses.includes("security"))
17
+ signals.push("security_relevant");
18
+ if (unit.required_lenses.includes("data_integrity"))
19
+ signals.push("writes_or_persistence");
20
+ if (unit.required_lenses.includes("config_deployment"))
21
+ signals.push("operational_surface");
22
+ const flowHits = unit.files.reduce((sum, path) => sum + (flowMap.get(path) ?? 0), 0);
23
+ if (flowHits > 0) {
24
+ signals.push("critical_flow_member");
25
+ }
26
+ const externalHits = unit.files.reduce((sum, path) => sum + (externalByPath.get(path) ?? 0), 0);
27
+ if (externalHits > 0) {
28
+ signals.push("external_analyzer_signal");
29
+ }
30
+ return {
31
+ unit_id: unit.unit_id,
32
+ risk_score: (unit.risk_score ?? 0) + flowHits + externalHits,
33
+ signals,
34
+ notes: [
35
+ "Initial heuristic risk scoring.",
36
+ ...(externalHits > 0
37
+ ? [
38
+ `External analyzer signals affecting ${externalHits} path match(es).`,
39
+ ]
40
+ : []),
41
+ ],
42
+ };
43
+ });
44
+ return { items };
45
+ }
@@ -0,0 +1,4 @@
1
+ import type { RepoManifest } from "../types.js";
2
+ import type { FileDisposition } from "../types/disposition.js";
3
+ import type { SurfaceManifest } from "../types/surfaces.js";
4
+ export declare function buildSurfaceManifest(repoManifest: RepoManifest, disposition?: FileDisposition): SurfaceManifest;