thuban 0.4.10 → 0.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +437 -437
- package/dist/LICENSE +21 -0
- package/dist/README.md +437 -0
- package/dist/cli.js +2 -0
- package/dist/package.json +63 -0
- package/dist/packages/crucible/.golden/golden-master.json +414 -0
- package/dist/packages/crucible/report-generator.js +1 -0
- package/dist/packages/crucible/rules/code-scanner-core.json +303 -0
- package/dist/packages/crucible/rules/command-injection.json +411 -0
- package/dist/packages/crucible/rules/crypto-misuse.json +35 -0
- package/dist/packages/crucible/rules/deserialization.json +152 -0
- package/dist/packages/crucible/rules/env-injection.json +46 -0
- package/dist/packages/crucible/rules/eval-abuse.json +104 -0
- package/dist/packages/crucible/rules/file-upload.json +46 -0
- package/dist/packages/crucible/rules/hallucination.json +22 -0
- package/dist/packages/crucible/rules/hardcoded-secret.json +397 -0
- package/dist/packages/crucible/rules/hardcoded-url.json +13 -0
- package/dist/packages/crucible/rules/insecure-crypto.json +302 -0
- package/dist/packages/crucible/rules/integer-overflow.json +35 -0
- package/dist/packages/crucible/rules/log-injection.json +33 -0
- package/dist/packages/crucible/rules/mass-assignment.json +112 -0
- package/dist/packages/crucible/rules/open-redirect.json +196 -0
- package/dist/packages/crucible/rules/path-traversal.json +422 -0
- package/dist/packages/crucible/rules/prototype-pollution.json +22 -0
- package/dist/packages/crucible/rules/sql-injection.json +619 -0
- package/dist/packages/crucible/rules/ssrf.json +557 -0
- package/dist/packages/crucible/rules/timing-attack.json +55 -0
- package/dist/packages/crucible/rules/unsafe-block.json +24 -0
- package/dist/packages/crucible/rules/xss.json +663 -0
- package/dist/packages/crucible/rules/xxe.json +66 -0
- package/dist/packages/crucible/rules/yaml-deserialization.json +22 -0
- package/dist/packages/crucible/rules/yaml-injection.json +22 -0
- package/dist/packages/crucible/seeds/csharp/seed-001.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-002.cs +24 -0
- package/dist/packages/crucible/seeds/csharp/seed-003.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-004.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-005.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-006.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-007.cs +34 -0
- package/dist/packages/crucible/seeds/csharp/seed-008.cs +23 -0
- package/dist/packages/crucible/seeds/csharp/seed-009.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-010.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-011.cs +32 -0
- package/dist/packages/crucible/seeds/csharp/seed-012.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-013.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-014.cs +26 -0
- package/dist/packages/crucible/seeds/csharp/seed-015.cs +33 -0
- package/dist/packages/crucible/seeds/csharp/seed-016.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-017.cs +22 -0
- package/dist/packages/crucible/seeds/csharp/seed-018.cs +26 -0
- package/dist/packages/crucible/seeds/csharp/seed-019.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-020.cs +22 -0
- package/dist/packages/crucible/seeds/csharp/seed-021.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-022.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-023.cs +33 -0
- package/dist/packages/crucible/seeds/csharp/seed-024.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-025.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-026.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-027.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-028.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-029.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-030.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-031.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-032.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-033.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-034.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-035.cs +32 -0
- package/dist/packages/crucible/seeds/csharp/seed-036.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-037.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-038.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-039.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-040.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-041.cs +33 -0
- package/dist/packages/crucible/seeds/csharp/seed-042.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-043.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-044.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-045.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-046.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-047.cs +26 -0
- package/dist/packages/crucible/seeds/csharp/seed-048.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-049.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-050.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-051.cs +34 -0
- package/dist/packages/crucible/seeds/csharp/seed-052.cs +36 -0
- package/dist/packages/crucible/seeds/go/seed-001.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-002.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-003.go +31 -0
- package/dist/packages/crucible/seeds/go/seed-004.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-005.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-006.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-007.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-008.go +25 -0
- package/dist/packages/crucible/seeds/go/seed-009.go +30 -0
- package/dist/packages/crucible/seeds/go/seed-010.go +35 -0
- package/dist/packages/crucible/seeds/go/seed-011.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-012.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-013.go +31 -0
- package/dist/packages/crucible/seeds/go/seed-014.go +35 -0
- package/dist/packages/crucible/seeds/go/seed-015.go +25 -0
- package/dist/packages/crucible/seeds/go/seed-016.go +19 -0
- package/dist/packages/crucible/seeds/go/seed-017.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-018.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-019.go +22 -0
- package/dist/packages/crucible/seeds/go/seed-020.go +31 -0
- package/dist/packages/crucible/seeds/go/seed-021.go +22 -0
- package/dist/packages/crucible/seeds/go/seed-022.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-023.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-024.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-025.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-026.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-027.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-028.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-029.go +28 -0
- package/dist/packages/crucible/seeds/go/seed-030.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-031.go +28 -0
- package/dist/packages/crucible/seeds/go/seed-032.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-033.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-034.go +22 -0
- package/dist/packages/crucible/seeds/go/seed-035.go +32 -0
- package/dist/packages/crucible/seeds/go/seed-036.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-037.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-038.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-039.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-040.go +37 -0
- package/dist/packages/crucible/seeds/go/seed-041.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-042.go +32 -0
- package/dist/packages/crucible/seeds/go/seed-043.go +35 -0
- package/dist/packages/crucible/seeds/go/seed-044.go +25 -0
- package/dist/packages/crucible/seeds/go/seed-045.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-046.go +34 -0
- package/dist/packages/crucible/seeds/go/seed-047.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-048.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-049.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-050.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-051.go +38 -0
- package/dist/packages/crucible/seeds/go/seed-052.go +27 -0
- package/dist/packages/crucible/seeds/java/seed-001.java +23 -0
- package/dist/packages/crucible/seeds/java/seed-002.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-003.java +28 -0
- package/dist/packages/crucible/seeds/java/seed-004.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-005.java +33 -0
- package/dist/packages/crucible/seeds/java/seed-006.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-007.java +21 -0
- package/dist/packages/crucible/seeds/java/seed-008.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-009.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-010.java +30 -0
- package/dist/packages/crucible/seeds/java/seed-011.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-012.java +20 -0
- package/dist/packages/crucible/seeds/java/seed-013.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-014.java +23 -0
- package/dist/packages/crucible/seeds/java/seed-015.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-016.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-017.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-018.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-019.java +38 -0
- package/dist/packages/crucible/seeds/java/seed-020.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-021.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-022.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-023.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-024.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-025.java +27 -0
- package/dist/packages/crucible/seeds/java/seed-026.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-027.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-028.java +21 -0
- package/dist/packages/crucible/seeds/java/seed-029.java +28 -0
- package/dist/packages/crucible/seeds/java/seed-030.java +27 -0
- package/dist/packages/crucible/seeds/java/seed-031.java +23 -0
- package/dist/packages/crucible/seeds/java/seed-032.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-033.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-034.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-035.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-036.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-037.java +30 -0
- package/dist/packages/crucible/seeds/java/seed-038.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-039.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-040.java +31 -0
- package/dist/packages/crucible/seeds/java/seed-041.java +20 -0
- package/dist/packages/crucible/seeds/java/seed-042.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-043.java +31 -0
- package/dist/packages/crucible/seeds/java/seed-044.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-045.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-046.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-047.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-048.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-049.java +28 -0
- package/dist/packages/crucible/seeds/java/seed-050.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-051.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-052.java +32 -0
- package/dist/packages/crucible/seeds/js/seed-001.js +27 -0
- package/dist/packages/crucible/seeds/js/seed-002.js +28 -0
- package/dist/packages/crucible/seeds/js/seed-003.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-004.js +28 -0
- package/dist/packages/crucible/seeds/js/seed-005.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-006.js +28 -0
- package/dist/packages/crucible/seeds/js/seed-007.js +26 -0
- package/dist/packages/crucible/seeds/js/seed-008.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-009.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-010.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-011.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-012.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-013.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-014.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-015.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-016.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-017.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-018.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-019.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-020.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-021.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-022.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-023.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-024.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-025.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-026.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-027.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-028.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-029.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-030.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-031.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-032.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-033.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-034.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-035.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-036.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-037.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-038.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-039.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-040.js +35 -0
- package/dist/packages/crucible/seeds/js/seed-041.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-042.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-043.js +27 -0
- package/dist/packages/crucible/seeds/js/seed-044.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-045.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-046.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-047.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-048.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-049.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-050.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-051.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-052.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-053.js +26 -0
- package/dist/packages/crucible/seeds/js/seed-054.js +35 -0
- package/dist/packages/crucible/seeds/js/seed-055.js +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-001.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-002.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-003.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-004.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-005.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-006.kt +21 -0
- package/dist/packages/crucible/seeds/kotlin/seed-007.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-008.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-009.kt +21 -0
- package/dist/packages/crucible/seeds/kotlin/seed-010.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-011.kt +22 -0
- package/dist/packages/crucible/seeds/kotlin/seed-012.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-013.kt +30 -0
- package/dist/packages/crucible/seeds/kotlin/seed-014.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-015.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-016.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-017.kt +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-018.kt +31 -0
- package/dist/packages/crucible/seeds/kotlin/seed-019.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-020.kt +31 -0
- package/dist/packages/crucible/seeds/kotlin/seed-021.kt +34 -0
- package/dist/packages/crucible/seeds/kotlin/seed-022.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-023.kt +20 -0
- package/dist/packages/crucible/seeds/kotlin/seed-024.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-025.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-026.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-027.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-028.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-029.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-030.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-031.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-032.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-033.kt +30 -0
- package/dist/packages/crucible/seeds/kotlin/seed-034.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-035.kt +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-036.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-037.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-038.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-039.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-040.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-041.kt +31 -0
- package/dist/packages/crucible/seeds/kotlin/seed-042.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-043.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-044.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-045.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-046.kt +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-047.kt +32 -0
- package/dist/packages/crucible/seeds/kotlin/seed-048.kt +20 -0
- package/dist/packages/crucible/seeds/kotlin/seed-049.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-050.kt +19 -0
- package/dist/packages/crucible/seeds/php/seed-001.php +23 -0
- package/dist/packages/crucible/seeds/php/seed-002.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-003.php +25 -0
- package/dist/packages/crucible/seeds/php/seed-004.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-005.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-006.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-007.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-008.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-009.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-010.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-011.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-012.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-013.php +23 -0
- package/dist/packages/crucible/seeds/php/seed-014.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-015.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-016.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-017.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-018.php +17 -0
- package/dist/packages/crucible/seeds/php/seed-019.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-020.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-021.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-022.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-023.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-024.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-025.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-026.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-027.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-028.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-029.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-030.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-031.php +23 -0
- package/dist/packages/crucible/seeds/php/seed-032.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-033.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-034.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-035.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-036.php +17 -0
- package/dist/packages/crucible/seeds/php/seed-037.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-038.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-039.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-040.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-041.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-042.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-043.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-044.php +25 -0
- package/dist/packages/crucible/seeds/php/seed-045.php +25 -0
- package/dist/packages/crucible/seeds/php/seed-046.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-047.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-048.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-049.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-050.php +20 -0
- package/dist/packages/crucible/seeds/python/seed-001.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-002.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-003.py +31 -0
- package/dist/packages/crucible/seeds/python/seed-004.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-005.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-006.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-007.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-008.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-009.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-010.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-011.py +30 -0
- package/dist/packages/crucible/seeds/python/seed-012.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-013.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-014.py +40 -0
- package/dist/packages/crucible/seeds/python/seed-015.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-016.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-017.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-018.py +30 -0
- package/dist/packages/crucible/seeds/python/seed-019.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-020.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-021 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-021.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-022 2.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-022.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-023 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-023.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-024 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-024.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-025 2.py +40 -0
- package/dist/packages/crucible/seeds/python/seed-025.py +40 -0
- package/dist/packages/crucible/seeds/python/seed-026 2.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-026.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-027 2.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-027.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-028 2.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-028.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-029.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-030 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-030.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-031 2.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-031.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-032.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-033.py +32 -0
- package/dist/packages/crucible/seeds/python/seed-034.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-035.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-036 2.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-036.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-037 2.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-037.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-038 2.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-038.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-039 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-039.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-040 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-040.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-041 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-041.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-042 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-042.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-043 2.py +32 -0
- package/dist/packages/crucible/seeds/python/seed-043.py +32 -0
- package/dist/packages/crucible/seeds/python/seed-044 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-044.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-045 2.py +36 -0
- package/dist/packages/crucible/seeds/python/seed-045.py +36 -0
- package/dist/packages/crucible/seeds/python/seed-046 2.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-046.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-047 2.py +44 -0
- package/dist/packages/crucible/seeds/python/seed-047.py +44 -0
- package/dist/packages/crucible/seeds/python/seed-048 2.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-048.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-049 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-049.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-050 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-050.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-051 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-051.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-052 2.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-052.py +41 -0
- package/dist/packages/crucible/seeds/ruby/seed-001 2.rb +15 -0
- package/dist/packages/crucible/seeds/ruby/seed-001.rb +15 -0
- package/dist/packages/crucible/seeds/ruby/seed-002 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-002.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-003 2.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-003.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-004 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-004.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-005 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-005.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-006 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-006.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-007 2.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-007.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-008 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-008.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-009 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-009.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-010 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-010.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-011 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-011.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-012 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-012.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-013 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-013.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-014 2.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-014.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-015 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-015.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-016 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-016.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-017 2.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-017.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-018 2.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-018.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-019 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-019.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-020 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-020.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-021 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-021.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-022 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-022.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-023 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-023.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-024 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-024.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-025 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-025.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-026 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-026.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-027 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-027.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-028 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-028.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-029 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-029.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-030 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-030.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-031 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-031.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-032 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-032.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-033 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-033.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-034 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-034.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-035 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-035.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-036 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-036.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-037 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-037.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-038 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-038.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-039 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-039.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-040 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-040.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-041 2.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-041.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-042 2.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-042.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-043 2.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-043.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-044 2.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-044.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-045 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-045.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-046 2.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-046.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-047 2.rb +26 -0
- package/dist/packages/crucible/seeds/ruby/seed-047.rb +26 -0
- package/dist/packages/crucible/seeds/ruby/seed-048 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-048.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-049 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-049.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-050 2.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-050.rb +27 -0
- package/dist/packages/crucible/seeds/rust/seed-001 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-001.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-002 2.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-002.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-003 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-003.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-004 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-004.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-005 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-005.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-006 2.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-006.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-007 2.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-007.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-008 2.rs +19 -0
- package/dist/packages/crucible/seeds/rust/seed-008.rs +19 -0
- package/dist/packages/crucible/seeds/rust/seed-009 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-009.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-010 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-010.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-011 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-011.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-012 2.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-012.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-013 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-013.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-014 2.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-014.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-015 2.rs +33 -0
- package/dist/packages/crucible/seeds/rust/seed-015.rs +33 -0
- package/dist/packages/crucible/seeds/rust/seed-016 2.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-016.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-017 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-017.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-018 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-018.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-019 2.rs +36 -0
- package/dist/packages/crucible/seeds/rust/seed-019.rs +36 -0
- package/dist/packages/crucible/seeds/rust/seed-020 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-020.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-021 2.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-021.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-022 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-022.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-023 2.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-023.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-024 2.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-024.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-025 2.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-025.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-026 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-026.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-027 2.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-027.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-028 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-028.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-029 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-029.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-030 2.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-030.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-031 2.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-031.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-032 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-032.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-033 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-033.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-034 2.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-034.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-035 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-035.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-036 2.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-036.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-037 2.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-037.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-038 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-038.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-039 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-039.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-040 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-040.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-041 2.rs +32 -0
- package/dist/packages/crucible/seeds/rust/seed-041.rs +32 -0
- package/dist/packages/crucible/seeds/rust/seed-042 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-042.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-043 2.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-043.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-044 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-044.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-045 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-045.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-046 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-046.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-047 2.rs +34 -0
- package/dist/packages/crucible/seeds/rust/seed-047.rs +34 -0
- package/dist/packages/crucible/seeds/rust/seed-048 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-048.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-049 2.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-049.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-050 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-050.rs +23 -0
- package/dist/packages/crucible/seeds/ts/seed-001 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-001.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-002 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-002.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-003 2.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-003.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-004 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-004.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-005 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-005.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-006 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-006.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-007 2.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-007.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-008 2.ts +40 -0
- package/dist/packages/crucible/seeds/ts/seed-008.ts +40 -0
- package/dist/packages/crucible/seeds/ts/seed-009 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-009.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-010 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-010.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-011 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-011.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-012 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-012.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-013 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-013.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-014 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-014.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-015 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-015.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-016 2.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-016.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-017 2.ts +44 -0
- package/dist/packages/crucible/seeds/ts/seed-017.ts +44 -0
- package/dist/packages/crucible/seeds/ts/seed-018 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-018.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-019 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-019.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-020 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-020.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-021 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-021.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-022 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-022.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-023 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-023.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-024 2.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-024.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-025 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-025.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-026 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-026.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-027 2.ts +30 -0
- package/dist/packages/crucible/seeds/ts/seed-027.ts +30 -0
- package/dist/packages/crucible/seeds/ts/seed-028 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-028.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-029 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-029.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-030 2.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-030.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-031 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-031.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-032 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-032.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-033 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-033.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-034 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-034.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-035 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-035.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-036 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-036.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-037 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-037.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-038 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-038.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-039 2.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-039.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-040 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-040.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-041 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-041.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-042 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-042.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-043 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-043.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-044 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-044.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-045 2.ts +39 -0
- package/dist/packages/crucible/seeds/ts/seed-045.ts +39 -0
- package/dist/packages/crucible/seeds/ts/seed-046 2.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-046.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-047 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-047.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-048 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-048.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-049 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-049.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-050 2.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-050.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-051 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-051.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-052 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-052.ts +36 -0
- package/dist/packages/scanner/alert-manager.js +1 -0
- package/dist/packages/scanner/architecture-map.js +1 -0
- package/dist/packages/scanner/ast-analyzer.js +1 -0
- package/dist/packages/scanner/benchmarks.js +1 -0
- package/dist/packages/scanner/cfg-analyzer.js +1 -0
- package/dist/packages/scanner/code-scanner.js +1 -0
- package/dist/packages/scanner/compliance-mapper.js +1 -0
- package/dist/packages/scanner/file-collector.js +1 -0
- package/dist/packages/scanner/file-watcher.js +1 -0
- package/dist/packages/scanner/ghost-code-detector.js +1 -0
- package/dist/packages/scanner/git-velocity.js +1 -0
- package/dist/packages/scanner/hallucination-detector.js +1 -0
- package/dist/packages/scanner/health-checker.js +1 -0
- package/dist/packages/scanner/investor-report.js +1 -0
- package/dist/packages/scanner/json-file-util.js +1 -0
- package/dist/packages/scanner/monitor-store.js +1 -0
- package/dist/packages/scanner/python_ast_helper.py +426 -0
- package/dist/packages/scanner/risk-valuation.js +1 -0
- package/dist/packages/scanner/scan-history.js +1 -0
- package/dist/packages/scanner/secret-scanner.js +1 -0
- package/dist/packages/scanner/sentinel-core.js +1 -0
- package/dist/packages/scanner/supply-chain.js +1 -0
- package/dist/packages/scanner/support-bot.js +1 -0
- package/dist/packages/scanner/support-knowledge.js +1 -0
- package/dist/packages/scanner/taint-tracker.js +1 -0
- package/package.json +15 -13
- package/cli.js +0 -2
- package/packages/crucible/.golden/golden-master.json +0 -414
- package/packages/crucible/README.md +0 -93
- package/packages/crucible/report-generator.js +0 -1
- package/packages/crucible/rules/code-scanner-core.json +0 -281
- package/packages/crucible/rules/command-injection.json +0 -411
- package/packages/crucible/rules/crypto-misuse.json +0 -35
- package/packages/crucible/rules/deserialization.json +0 -152
- package/packages/crucible/rules/env-injection.json +0 -46
- package/packages/crucible/rules/eval-abuse.json +0 -104
- package/packages/crucible/rules/file-upload.json +0 -46
- package/packages/crucible/rules/hallucination.json +0 -22
- package/packages/crucible/rules/hardcoded-secret.json +0 -397
- package/packages/crucible/rules/hardcoded-url.json +0 -13
- package/packages/crucible/rules/insecure-crypto.json +0 -302
- package/packages/crucible/rules/integer-overflow.json +0 -35
- package/packages/crucible/rules/log-injection.json +0 -33
- package/packages/crucible/rules/mass-assignment.json +0 -112
- package/packages/crucible/rules/open-redirect.json +0 -196
- package/packages/crucible/rules/path-traversal.json +0 -422
- package/packages/crucible/rules/prototype-pollution.json +0 -22
- package/packages/crucible/rules/sql-injection.json +0 -619
- package/packages/crucible/rules/ssrf.json +0 -557
- package/packages/crucible/rules/timing-attack.json +0 -55
- package/packages/crucible/rules/unsafe-block.json +0 -24
- package/packages/crucible/rules/xss.json +0 -663
- package/packages/crucible/rules/xxe.json +0 -66
- package/packages/crucible/rules/yaml-deserialization.json +0 -22
- package/packages/crucible/rules/yaml-injection.json +0 -22
- package/packages/crucible/seeds/csharp/seed-001.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-002.cs +0 -24
- package/packages/crucible/seeds/csharp/seed-003.cs +0 -30
- package/packages/crucible/seeds/csharp/seed-004.cs +0 -31
- package/packages/crucible/seeds/csharp/seed-005.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-006.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-007.cs +0 -34
- package/packages/crucible/seeds/csharp/seed-008.cs +0 -23
- package/packages/crucible/seeds/csharp/seed-009.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-010.cs +0 -29
- package/packages/crucible/seeds/csharp/seed-011.cs +0 -32
- package/packages/crucible/seeds/csharp/seed-012.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-013.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-014.cs +0 -26
- package/packages/crucible/seeds/csharp/seed-015.cs +0 -33
- package/packages/crucible/seeds/csharp/seed-016.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-017.cs +0 -22
- package/packages/crucible/seeds/csharp/seed-018.cs +0 -26
- package/packages/crucible/seeds/csharp/seed-019.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-020.cs +0 -22
- package/packages/crucible/seeds/csharp/seed-021.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-022.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-023.cs +0 -33
- package/packages/crucible/seeds/csharp/seed-024.cs +0 -31
- package/packages/crucible/seeds/csharp/seed-025.cs +0 -31
- package/packages/crucible/seeds/csharp/seed-026.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-027.cs +0 -29
- package/packages/crucible/seeds/csharp/seed-028.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-029.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-030.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-031.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-032.cs +0 -30
- package/packages/crucible/seeds/csharp/seed-033.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-034.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-035.cs +0 -32
- package/packages/crucible/seeds/csharp/seed-036.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-037.cs +0 -29
- package/packages/crucible/seeds/csharp/seed-038.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-039.cs +0 -29
- package/packages/crucible/seeds/csharp/seed-040.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-041.cs +0 -33
- package/packages/crucible/seeds/csharp/seed-042.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-043.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-044.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-045.cs +0 -30
- package/packages/crucible/seeds/csharp/seed-046.cs +0 -29
- package/packages/crucible/seeds/csharp/seed-047.cs +0 -26
- package/packages/crucible/seeds/csharp/seed-048.cs +0 -31
- package/packages/crucible/seeds/csharp/seed-049.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-050.cs +0 -30
- package/packages/crucible/seeds/csharp/seed-051.cs +0 -34
- package/packages/crucible/seeds/csharp/seed-052.cs +0 -36
- package/packages/crucible/seeds/go/seed-001.go +0 -29
- package/packages/crucible/seeds/go/seed-002.go +0 -27
- package/packages/crucible/seeds/go/seed-003.go +0 -31
- package/packages/crucible/seeds/go/seed-004.go +0 -27
- package/packages/crucible/seeds/go/seed-005.go +0 -27
- package/packages/crucible/seeds/go/seed-006.go +0 -29
- package/packages/crucible/seeds/go/seed-007.go +0 -24
- package/packages/crucible/seeds/go/seed-008.go +0 -25
- package/packages/crucible/seeds/go/seed-009.go +0 -30
- package/packages/crucible/seeds/go/seed-010.go +0 -35
- package/packages/crucible/seeds/go/seed-011.go +0 -24
- package/packages/crucible/seeds/go/seed-012.go +0 -24
- package/packages/crucible/seeds/go/seed-013.go +0 -31
- package/packages/crucible/seeds/go/seed-014.go +0 -35
- package/packages/crucible/seeds/go/seed-015.go +0 -25
- package/packages/crucible/seeds/go/seed-016.go +0 -19
- package/packages/crucible/seeds/go/seed-017.go +0 -23
- package/packages/crucible/seeds/go/seed-018.go +0 -23
- package/packages/crucible/seeds/go/seed-019.go +0 -22
- package/packages/crucible/seeds/go/seed-020.go +0 -31
- package/packages/crucible/seeds/go/seed-021.go +0 -22
- package/packages/crucible/seeds/go/seed-022.go +0 -29
- package/packages/crucible/seeds/go/seed-023.go +0 -26
- package/packages/crucible/seeds/go/seed-024.go +0 -27
- package/packages/crucible/seeds/go/seed-025.go +0 -23
- package/packages/crucible/seeds/go/seed-026.go +0 -29
- package/packages/crucible/seeds/go/seed-027.go +0 -26
- package/packages/crucible/seeds/go/seed-028.go +0 -23
- package/packages/crucible/seeds/go/seed-029.go +0 -28
- package/packages/crucible/seeds/go/seed-030.go +0 -27
- package/packages/crucible/seeds/go/seed-031.go +0 -28
- package/packages/crucible/seeds/go/seed-032.go +0 -27
- package/packages/crucible/seeds/go/seed-033.go +0 -29
- package/packages/crucible/seeds/go/seed-034.go +0 -22
- package/packages/crucible/seeds/go/seed-035.go +0 -32
- package/packages/crucible/seeds/go/seed-036.go +0 -27
- package/packages/crucible/seeds/go/seed-037.go +0 -27
- package/packages/crucible/seeds/go/seed-038.go +0 -27
- package/packages/crucible/seeds/go/seed-039.go +0 -26
- package/packages/crucible/seeds/go/seed-040.go +0 -37
- package/packages/crucible/seeds/go/seed-041.go +0 -23
- package/packages/crucible/seeds/go/seed-042.go +0 -32
- package/packages/crucible/seeds/go/seed-043.go +0 -35
- package/packages/crucible/seeds/go/seed-044.go +0 -25
- package/packages/crucible/seeds/go/seed-045.go +0 -26
- package/packages/crucible/seeds/go/seed-046.go +0 -34
- package/packages/crucible/seeds/go/seed-047.go +0 -26
- package/packages/crucible/seeds/go/seed-048.go +0 -29
- package/packages/crucible/seeds/go/seed-049.go +0 -24
- package/packages/crucible/seeds/go/seed-050.go +0 -27
- package/packages/crucible/seeds/go/seed-051.go +0 -38
- package/packages/crucible/seeds/go/seed-052.go +0 -27
- package/packages/crucible/seeds/java/seed-001.java +0 -23
- package/packages/crucible/seeds/java/seed-002.java +0 -22
- package/packages/crucible/seeds/java/seed-003.java +0 -28
- package/packages/crucible/seeds/java/seed-004.java +0 -26
- package/packages/crucible/seeds/java/seed-005.java +0 -33
- package/packages/crucible/seeds/java/seed-006.java +0 -22
- package/packages/crucible/seeds/java/seed-007.java +0 -21
- package/packages/crucible/seeds/java/seed-008.java +0 -29
- package/packages/crucible/seeds/java/seed-009.java +0 -24
- package/packages/crucible/seeds/java/seed-010.java +0 -30
- package/packages/crucible/seeds/java/seed-011.java +0 -25
- package/packages/crucible/seeds/java/seed-012.java +0 -20
- package/packages/crucible/seeds/java/seed-013.java +0 -26
- package/packages/crucible/seeds/java/seed-014.java +0 -23
- package/packages/crucible/seeds/java/seed-015.java +0 -25
- package/packages/crucible/seeds/java/seed-016.java +0 -22
- package/packages/crucible/seeds/java/seed-017.java +0 -24
- package/packages/crucible/seeds/java/seed-018.java +0 -24
- package/packages/crucible/seeds/java/seed-019.java +0 -38
- package/packages/crucible/seeds/java/seed-020.java +0 -24
- package/packages/crucible/seeds/java/seed-021.java +0 -22
- package/packages/crucible/seeds/java/seed-022.java +0 -22
- package/packages/crucible/seeds/java/seed-023.java +0 -22
- package/packages/crucible/seeds/java/seed-024.java +0 -25
- package/packages/crucible/seeds/java/seed-025.java +0 -27
- package/packages/crucible/seeds/java/seed-026.java +0 -25
- package/packages/crucible/seeds/java/seed-027.java +0 -22
- package/packages/crucible/seeds/java/seed-028.java +0 -21
- package/packages/crucible/seeds/java/seed-029.java +0 -28
- package/packages/crucible/seeds/java/seed-030.java +0 -27
- package/packages/crucible/seeds/java/seed-031.java +0 -23
- package/packages/crucible/seeds/java/seed-032.java +0 -22
- package/packages/crucible/seeds/java/seed-033.java +0 -24
- package/packages/crucible/seeds/java/seed-034.java +0 -24
- package/packages/crucible/seeds/java/seed-035.java +0 -29
- package/packages/crucible/seeds/java/seed-036.java +0 -25
- package/packages/crucible/seeds/java/seed-037.java +0 -30
- package/packages/crucible/seeds/java/seed-038.java +0 -29
- package/packages/crucible/seeds/java/seed-039.java +0 -26
- package/packages/crucible/seeds/java/seed-040.java +0 -31
- package/packages/crucible/seeds/java/seed-041.java +0 -20
- package/packages/crucible/seeds/java/seed-042.java +0 -26
- package/packages/crucible/seeds/java/seed-043.java +0 -31
- package/packages/crucible/seeds/java/seed-044.java +0 -22
- package/packages/crucible/seeds/java/seed-045.java +0 -25
- package/packages/crucible/seeds/java/seed-046.java +0 -22
- package/packages/crucible/seeds/java/seed-047.java +0 -26
- package/packages/crucible/seeds/java/seed-048.java +0 -24
- package/packages/crucible/seeds/java/seed-049.java +0 -28
- package/packages/crucible/seeds/java/seed-050.java +0 -29
- package/packages/crucible/seeds/java/seed-051.java +0 -25
- package/packages/crucible/seeds/java/seed-052.java +0 -32
- package/packages/crucible/seeds/js/seed-001.js +0 -27
- package/packages/crucible/seeds/js/seed-002.js +0 -28
- package/packages/crucible/seeds/js/seed-003.js +0 -30
- package/packages/crucible/seeds/js/seed-004.js +0 -28
- package/packages/crucible/seeds/js/seed-005.js +0 -31
- package/packages/crucible/seeds/js/seed-006.js +0 -28
- package/packages/crucible/seeds/js/seed-007.js +0 -26
- package/packages/crucible/seeds/js/seed-008.js +0 -30
- package/packages/crucible/seeds/js/seed-009.js +0 -30
- package/packages/crucible/seeds/js/seed-010.js +0 -29
- package/packages/crucible/seeds/js/seed-011.js +0 -34
- package/packages/crucible/seeds/js/seed-012.js +0 -32
- package/packages/crucible/seeds/js/seed-013.js +0 -29
- package/packages/crucible/seeds/js/seed-014.js +0 -29
- package/packages/crucible/seeds/js/seed-015.js +0 -31
- package/packages/crucible/seeds/js/seed-016.js +0 -31
- package/packages/crucible/seeds/js/seed-017.js +0 -30
- package/packages/crucible/seeds/js/seed-018.js +0 -29
- package/packages/crucible/seeds/js/seed-019.js +0 -32
- package/packages/crucible/seeds/js/seed-020.js +0 -29
- package/packages/crucible/seeds/js/seed-021.js +0 -31
- package/packages/crucible/seeds/js/seed-022.js +0 -31
- package/packages/crucible/seeds/js/seed-023.js +0 -29
- package/packages/crucible/seeds/js/seed-024.js +0 -29
- package/packages/crucible/seeds/js/seed-025.js +0 -34
- package/packages/crucible/seeds/js/seed-026.js +0 -31
- package/packages/crucible/seeds/js/seed-027.js +0 -31
- package/packages/crucible/seeds/js/seed-028.js +0 -33
- package/packages/crucible/seeds/js/seed-029.js +0 -33
- package/packages/crucible/seeds/js/seed-030.js +0 -30
- package/packages/crucible/seeds/js/seed-031.js +0 -31
- package/packages/crucible/seeds/js/seed-032.js +0 -34
- package/packages/crucible/seeds/js/seed-033.js +0 -33
- package/packages/crucible/seeds/js/seed-034.js +0 -33
- package/packages/crucible/seeds/js/seed-035.js +0 -30
- package/packages/crucible/seeds/js/seed-036.js +0 -30
- package/packages/crucible/seeds/js/seed-037.js +0 -29
- package/packages/crucible/seeds/js/seed-038.js +0 -31
- package/packages/crucible/seeds/js/seed-039.js +0 -34
- package/packages/crucible/seeds/js/seed-040.js +0 -35
- package/packages/crucible/seeds/js/seed-041.js +0 -32
- package/packages/crucible/seeds/js/seed-042.js +0 -32
- package/packages/crucible/seeds/js/seed-043.js +0 -27
- package/packages/crucible/seeds/js/seed-044.js +0 -29
- package/packages/crucible/seeds/js/seed-045.js +0 -33
- package/packages/crucible/seeds/js/seed-046.js +0 -33
- package/packages/crucible/seeds/js/seed-047.js +0 -29
- package/packages/crucible/seeds/js/seed-048.js +0 -29
- package/packages/crucible/seeds/js/seed-049.js +0 -34
- package/packages/crucible/seeds/js/seed-050.js +0 -34
- package/packages/crucible/seeds/js/seed-051.js +0 -30
- package/packages/crucible/seeds/js/seed-052.js +0 -30
- package/packages/crucible/seeds/js/seed-053.js +0 -26
- package/packages/crucible/seeds/js/seed-054.js +0 -35
- package/packages/crucible/seeds/js/seed-055.js +0 -33
- package/packages/crucible/seeds/kotlin/seed-001.kt +0 -24
- package/packages/crucible/seeds/kotlin/seed-002.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-003.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-004.kt +0 -24
- package/packages/crucible/seeds/kotlin/seed-005.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-006.kt +0 -21
- package/packages/crucible/seeds/kotlin/seed-007.kt +0 -23
- package/packages/crucible/seeds/kotlin/seed-008.kt +0 -25
- package/packages/crucible/seeds/kotlin/seed-009.kt +0 -21
- package/packages/crucible/seeds/kotlin/seed-010.kt +0 -28
- package/packages/crucible/seeds/kotlin/seed-011.kt +0 -22
- package/packages/crucible/seeds/kotlin/seed-012.kt +0 -25
- package/packages/crucible/seeds/kotlin/seed-013.kt +0 -30
- package/packages/crucible/seeds/kotlin/seed-014.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-015.kt +0 -24
- package/packages/crucible/seeds/kotlin/seed-016.kt +0 -28
- package/packages/crucible/seeds/kotlin/seed-017.kt +0 -33
- package/packages/crucible/seeds/kotlin/seed-018.kt +0 -31
- package/packages/crucible/seeds/kotlin/seed-019.kt +0 -28
- package/packages/crucible/seeds/kotlin/seed-020.kt +0 -31
- package/packages/crucible/seeds/kotlin/seed-021.kt +0 -34
- package/packages/crucible/seeds/kotlin/seed-022.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-023.kt +0 -20
- package/packages/crucible/seeds/kotlin/seed-024.kt +0 -23
- package/packages/crucible/seeds/kotlin/seed-025.kt +0 -23
- package/packages/crucible/seeds/kotlin/seed-026.kt +0 -26
- package/packages/crucible/seeds/kotlin/seed-027.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-028.kt +0 -24
- package/packages/crucible/seeds/kotlin/seed-029.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-030.kt +0 -26
- package/packages/crucible/seeds/kotlin/seed-031.kt +0 -28
- package/packages/crucible/seeds/kotlin/seed-032.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-033.kt +0 -30
- package/packages/crucible/seeds/kotlin/seed-034.kt +0 -26
- package/packages/crucible/seeds/kotlin/seed-035.kt +0 -33
- package/packages/crucible/seeds/kotlin/seed-036.kt +0 -25
- package/packages/crucible/seeds/kotlin/seed-037.kt +0 -26
- package/packages/crucible/seeds/kotlin/seed-038.kt +0 -25
- package/packages/crucible/seeds/kotlin/seed-039.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-040.kt +0 -28
- package/packages/crucible/seeds/kotlin/seed-041.kt +0 -31
- package/packages/crucible/seeds/kotlin/seed-042.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-043.kt +0 -26
- package/packages/crucible/seeds/kotlin/seed-044.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-045.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-046.kt +0 -33
- package/packages/crucible/seeds/kotlin/seed-047.kt +0 -32
- package/packages/crucible/seeds/kotlin/seed-048.kt +0 -20
- package/packages/crucible/seeds/kotlin/seed-049.kt +0 -23
- package/packages/crucible/seeds/kotlin/seed-050.kt +0 -19
- package/packages/crucible/seeds/php/seed-001.php +0 -23
- package/packages/crucible/seeds/php/seed-002.php +0 -18
- package/packages/crucible/seeds/php/seed-003.php +0 -25
- package/packages/crucible/seeds/php/seed-004.php +0 -21
- package/packages/crucible/seeds/php/seed-005.php +0 -21
- package/packages/crucible/seeds/php/seed-006.php +0 -21
- package/packages/crucible/seeds/php/seed-007.php +0 -18
- package/packages/crucible/seeds/php/seed-008.php +0 -19
- package/packages/crucible/seeds/php/seed-009.php +0 -24
- package/packages/crucible/seeds/php/seed-010.php +0 -24
- package/packages/crucible/seeds/php/seed-011.php +0 -18
- package/packages/crucible/seeds/php/seed-012.php +0 -24
- package/packages/crucible/seeds/php/seed-013.php +0 -23
- package/packages/crucible/seeds/php/seed-014.php +0 -20
- package/packages/crucible/seeds/php/seed-015.php +0 -18
- package/packages/crucible/seeds/php/seed-016.php +0 -18
- package/packages/crucible/seeds/php/seed-017.php +0 -18
- package/packages/crucible/seeds/php/seed-018.php +0 -17
- package/packages/crucible/seeds/php/seed-019.php +0 -24
- package/packages/crucible/seeds/php/seed-020.php +0 -19
- package/packages/crucible/seeds/php/seed-021.php +0 -22
- package/packages/crucible/seeds/php/seed-022.php +0 -15
- package/packages/crucible/seeds/php/seed-023.php +0 -24
- package/packages/crucible/seeds/php/seed-024.php +0 -22
- package/packages/crucible/seeds/php/seed-025.php +0 -20
- package/packages/crucible/seeds/php/seed-026.php +0 -22
- package/packages/crucible/seeds/php/seed-027.php +0 -15
- package/packages/crucible/seeds/php/seed-028.php +0 -15
- package/packages/crucible/seeds/php/seed-029.php +0 -21
- package/packages/crucible/seeds/php/seed-030.php +0 -21
- package/packages/crucible/seeds/php/seed-031.php +0 -23
- package/packages/crucible/seeds/php/seed-032.php +0 -18
- package/packages/crucible/seeds/php/seed-033.php +0 -18
- package/packages/crucible/seeds/php/seed-034.php +0 -24
- package/packages/crucible/seeds/php/seed-035.php +0 -22
- package/packages/crucible/seeds/php/seed-036.php +0 -17
- package/packages/crucible/seeds/php/seed-037.php +0 -19
- package/packages/crucible/seeds/php/seed-038.php +0 -20
- package/packages/crucible/seeds/php/seed-039.php +0 -15
- package/packages/crucible/seeds/php/seed-040.php +0 -21
- package/packages/crucible/seeds/php/seed-041.php +0 -20
- package/packages/crucible/seeds/php/seed-042.php +0 -21
- package/packages/crucible/seeds/php/seed-043.php +0 -21
- package/packages/crucible/seeds/php/seed-044.php +0 -25
- package/packages/crucible/seeds/php/seed-045.php +0 -25
- package/packages/crucible/seeds/php/seed-046.php +0 -20
- package/packages/crucible/seeds/php/seed-047.php +0 -21
- package/packages/crucible/seeds/php/seed-048.php +0 -19
- package/packages/crucible/seeds/php/seed-049.php +0 -18
- package/packages/crucible/seeds/php/seed-050.php +0 -20
- package/packages/crucible/seeds/python/seed-001.py +0 -33
- package/packages/crucible/seeds/python/seed-002.py +0 -39
- package/packages/crucible/seeds/python/seed-003.py +0 -31
- package/packages/crucible/seeds/python/seed-004.py +0 -33
- package/packages/crucible/seeds/python/seed-005.py +0 -33
- package/packages/crucible/seeds/python/seed-006.py +0 -34
- package/packages/crucible/seeds/python/seed-007.py +0 -33
- package/packages/crucible/seeds/python/seed-008.py +0 -38
- package/packages/crucible/seeds/python/seed-009.py +0 -38
- package/packages/crucible/seeds/python/seed-010.py +0 -42
- package/packages/crucible/seeds/python/seed-011.py +0 -30
- package/packages/crucible/seeds/python/seed-012.py +0 -35
- package/packages/crucible/seeds/python/seed-013.py +0 -33
- package/packages/crucible/seeds/python/seed-014.py +0 -40
- package/packages/crucible/seeds/python/seed-015.py +0 -33
- package/packages/crucible/seeds/python/seed-016.py +0 -34
- package/packages/crucible/seeds/python/seed-017.py +0 -34
- package/packages/crucible/seeds/python/seed-018.py +0 -30
- package/packages/crucible/seeds/python/seed-019.py +0 -33
- package/packages/crucible/seeds/python/seed-020.py +0 -37
- package/packages/crucible/seeds/python/seed-021 2.py +0 -37
- package/packages/crucible/seeds/python/seed-021.py +0 -37
- package/packages/crucible/seeds/python/seed-022 2.py +0 -34
- package/packages/crucible/seeds/python/seed-022.py +0 -34
- package/packages/crucible/seeds/python/seed-023 2.py +0 -37
- package/packages/crucible/seeds/python/seed-023.py +0 -37
- package/packages/crucible/seeds/python/seed-024 2.py +0 -38
- package/packages/crucible/seeds/python/seed-024.py +0 -38
- package/packages/crucible/seeds/python/seed-025 2.py +0 -40
- package/packages/crucible/seeds/python/seed-025.py +0 -40
- package/packages/crucible/seeds/python/seed-026 2.py +0 -35
- package/packages/crucible/seeds/python/seed-026.py +0 -35
- package/packages/crucible/seeds/python/seed-027 2.py +0 -35
- package/packages/crucible/seeds/python/seed-027.py +0 -35
- package/packages/crucible/seeds/python/seed-028 2.py +0 -42
- package/packages/crucible/seeds/python/seed-028.py +0 -42
- package/packages/crucible/seeds/python/seed-029.py +0 -42
- package/packages/crucible/seeds/python/seed-030 2.py +0 -37
- package/packages/crucible/seeds/python/seed-030.py +0 -37
- package/packages/crucible/seeds/python/seed-031 2.py +0 -34
- package/packages/crucible/seeds/python/seed-031.py +0 -34
- package/packages/crucible/seeds/python/seed-032.py +0 -33
- package/packages/crucible/seeds/python/seed-033.py +0 -32
- package/packages/crucible/seeds/python/seed-034.py +0 -38
- package/packages/crucible/seeds/python/seed-035.py +0 -35
- package/packages/crucible/seeds/python/seed-036 2.py +0 -33
- package/packages/crucible/seeds/python/seed-036.py +0 -33
- package/packages/crucible/seeds/python/seed-037 2.py +0 -41
- package/packages/crucible/seeds/python/seed-037.py +0 -41
- package/packages/crucible/seeds/python/seed-038 2.py +0 -33
- package/packages/crucible/seeds/python/seed-038.py +0 -33
- package/packages/crucible/seeds/python/seed-039 2.py +0 -39
- package/packages/crucible/seeds/python/seed-039.py +0 -39
- package/packages/crucible/seeds/python/seed-040 2.py +0 -39
- package/packages/crucible/seeds/python/seed-040.py +0 -39
- package/packages/crucible/seeds/python/seed-041 2.py +0 -37
- package/packages/crucible/seeds/python/seed-041.py +0 -37
- package/packages/crucible/seeds/python/seed-042 2.py +0 -38
- package/packages/crucible/seeds/python/seed-042.py +0 -38
- package/packages/crucible/seeds/python/seed-043 2.py +0 -32
- package/packages/crucible/seeds/python/seed-043.py +0 -32
- package/packages/crucible/seeds/python/seed-044 2.py +0 -38
- package/packages/crucible/seeds/python/seed-044.py +0 -38
- package/packages/crucible/seeds/python/seed-045 2.py +0 -36
- package/packages/crucible/seeds/python/seed-045.py +0 -36
- package/packages/crucible/seeds/python/seed-046 2.py +0 -33
- package/packages/crucible/seeds/python/seed-046.py +0 -33
- package/packages/crucible/seeds/python/seed-047 2.py +0 -44
- package/packages/crucible/seeds/python/seed-047.py +0 -44
- package/packages/crucible/seeds/python/seed-048 2.py +0 -35
- package/packages/crucible/seeds/python/seed-048.py +0 -35
- package/packages/crucible/seeds/python/seed-049 2.py +0 -39
- package/packages/crucible/seeds/python/seed-049.py +0 -39
- package/packages/crucible/seeds/python/seed-050 2.py +0 -39
- package/packages/crucible/seeds/python/seed-050.py +0 -39
- package/packages/crucible/seeds/python/seed-051 2.py +0 -38
- package/packages/crucible/seeds/python/seed-051.py +0 -38
- package/packages/crucible/seeds/python/seed-052 2.py +0 -41
- package/packages/crucible/seeds/python/seed-052.py +0 -41
- package/packages/crucible/seeds/ruby/seed-001 2.rb +0 -15
- package/packages/crucible/seeds/ruby/seed-001.rb +0 -15
- package/packages/crucible/seeds/ruby/seed-002 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-002.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-003 2.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-003.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-004 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-004.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-005 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-005.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-006 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-006.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-007 2.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-007.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-008 2.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-008.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-009 2.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-009.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-010 2.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-010.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-011 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-011.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-012 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-012.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-013 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-013.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-014 2.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-014.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-015 2.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-015.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-016 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-016.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-017 2.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-017.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-018 2.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-018.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-019 2.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-019.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-020 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-020.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-021 2.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-021.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-022 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-022.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-023 2.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-023.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-024 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-024.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-025 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-025.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-026 2.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-026.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-027 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-027.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-028 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-028.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-029 2.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-029.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-030 2.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-030.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-031 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-031.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-032 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-032.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-033 2.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-033.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-034 2.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-034.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-035 2.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-035.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-036 2.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-036.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-037 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-037.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-038 2.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-038.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-039 2.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-039.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-040 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-040.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-041 2.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-041.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-042 2.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-042.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-043 2.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-043.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-044 2.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-044.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-045 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-045.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-046 2.rb +0 -27
- package/packages/crucible/seeds/ruby/seed-046.rb +0 -27
- package/packages/crucible/seeds/ruby/seed-047 2.rb +0 -26
- package/packages/crucible/seeds/ruby/seed-047.rb +0 -26
- package/packages/crucible/seeds/ruby/seed-048 2.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-048.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-049 2.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-049.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-050 2.rb +0 -27
- package/packages/crucible/seeds/ruby/seed-050.rb +0 -27
- package/packages/crucible/seeds/rust/seed-001 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-001.rs +0 -25
- package/packages/crucible/seeds/rust/seed-002 2.rs +0 -20
- package/packages/crucible/seeds/rust/seed-002.rs +0 -20
- package/packages/crucible/seeds/rust/seed-003 2.rs +0 -23
- package/packages/crucible/seeds/rust/seed-003.rs +0 -23
- package/packages/crucible/seeds/rust/seed-004 2.rs +0 -21
- package/packages/crucible/seeds/rust/seed-004.rs +0 -21
- package/packages/crucible/seeds/rust/seed-005 2.rs +0 -21
- package/packages/crucible/seeds/rust/seed-005.rs +0 -21
- package/packages/crucible/seeds/rust/seed-006 2.rs +0 -24
- package/packages/crucible/seeds/rust/seed-006.rs +0 -24
- package/packages/crucible/seeds/rust/seed-007 2.rs +0 -20
- package/packages/crucible/seeds/rust/seed-007.rs +0 -20
- package/packages/crucible/seeds/rust/seed-008 2.rs +0 -19
- package/packages/crucible/seeds/rust/seed-008.rs +0 -19
- package/packages/crucible/seeds/rust/seed-009 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-009.rs +0 -28
- package/packages/crucible/seeds/rust/seed-010 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-010.rs +0 -28
- package/packages/crucible/seeds/rust/seed-011 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-011.rs +0 -25
- package/packages/crucible/seeds/rust/seed-012 2.rs +0 -31
- package/packages/crucible/seeds/rust/seed-012.rs +0 -31
- package/packages/crucible/seeds/rust/seed-013 2.rs +0 -27
- package/packages/crucible/seeds/rust/seed-013.rs +0 -27
- package/packages/crucible/seeds/rust/seed-014 2.rs +0 -30
- package/packages/crucible/seeds/rust/seed-014.rs +0 -30
- package/packages/crucible/seeds/rust/seed-015 2.rs +0 -33
- package/packages/crucible/seeds/rust/seed-015.rs +0 -33
- package/packages/crucible/seeds/rust/seed-016 2.rs +0 -22
- package/packages/crucible/seeds/rust/seed-016.rs +0 -22
- package/packages/crucible/seeds/rust/seed-017 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-017.rs +0 -28
- package/packages/crucible/seeds/rust/seed-018 2.rs +0 -21
- package/packages/crucible/seeds/rust/seed-018.rs +0 -21
- package/packages/crucible/seeds/rust/seed-019 2.rs +0 -36
- package/packages/crucible/seeds/rust/seed-019.rs +0 -36
- package/packages/crucible/seeds/rust/seed-020 2.rs +0 -27
- package/packages/crucible/seeds/rust/seed-020.rs +0 -27
- package/packages/crucible/seeds/rust/seed-021 2.rs +0 -26
- package/packages/crucible/seeds/rust/seed-021.rs +0 -26
- package/packages/crucible/seeds/rust/seed-022 2.rs +0 -23
- package/packages/crucible/seeds/rust/seed-022.rs +0 -23
- package/packages/crucible/seeds/rust/seed-023 2.rs +0 -22
- package/packages/crucible/seeds/rust/seed-023.rs +0 -22
- package/packages/crucible/seeds/rust/seed-024 2.rs +0 -24
- package/packages/crucible/seeds/rust/seed-024.rs +0 -24
- package/packages/crucible/seeds/rust/seed-025 2.rs +0 -29
- package/packages/crucible/seeds/rust/seed-025.rs +0 -29
- package/packages/crucible/seeds/rust/seed-026 2.rs +0 -23
- package/packages/crucible/seeds/rust/seed-026.rs +0 -23
- package/packages/crucible/seeds/rust/seed-027 2.rs +0 -24
- package/packages/crucible/seeds/rust/seed-027.rs +0 -24
- package/packages/crucible/seeds/rust/seed-028 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-028.rs +0 -25
- package/packages/crucible/seeds/rust/seed-029 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-029.rs +0 -25
- package/packages/crucible/seeds/rust/seed-030 2.rs +0 -30
- package/packages/crucible/seeds/rust/seed-030.rs +0 -30
- package/packages/crucible/seeds/rust/seed-031 2.rs +0 -22
- package/packages/crucible/seeds/rust/seed-031.rs +0 -22
- package/packages/crucible/seeds/rust/seed-032 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-032.rs +0 -25
- package/packages/crucible/seeds/rust/seed-033 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-033.rs +0 -25
- package/packages/crucible/seeds/rust/seed-034 2.rs +0 -20
- package/packages/crucible/seeds/rust/seed-034.rs +0 -20
- package/packages/crucible/seeds/rust/seed-035 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-035.rs +0 -28
- package/packages/crucible/seeds/rust/seed-036 2.rs +0 -26
- package/packages/crucible/seeds/rust/seed-036.rs +0 -26
- package/packages/crucible/seeds/rust/seed-037 2.rs +0 -31
- package/packages/crucible/seeds/rust/seed-037.rs +0 -31
- package/packages/crucible/seeds/rust/seed-038 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-038.rs +0 -25
- package/packages/crucible/seeds/rust/seed-039 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-039.rs +0 -28
- package/packages/crucible/seeds/rust/seed-040 2.rs +0 -27
- package/packages/crucible/seeds/rust/seed-040.rs +0 -27
- package/packages/crucible/seeds/rust/seed-041 2.rs +0 -32
- package/packages/crucible/seeds/rust/seed-041.rs +0 -32
- package/packages/crucible/seeds/rust/seed-042 2.rs +0 -27
- package/packages/crucible/seeds/rust/seed-042.rs +0 -27
- package/packages/crucible/seeds/rust/seed-043 2.rs +0 -29
- package/packages/crucible/seeds/rust/seed-043.rs +0 -29
- package/packages/crucible/seeds/rust/seed-044 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-044.rs +0 -25
- package/packages/crucible/seeds/rust/seed-045 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-045.rs +0 -28
- package/packages/crucible/seeds/rust/seed-046 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-046.rs +0 -25
- package/packages/crucible/seeds/rust/seed-047 2.rs +0 -34
- package/packages/crucible/seeds/rust/seed-047.rs +0 -34
- package/packages/crucible/seeds/rust/seed-048 2.rs +0 -21
- package/packages/crucible/seeds/rust/seed-048.rs +0 -21
- package/packages/crucible/seeds/rust/seed-049 2.rs +0 -26
- package/packages/crucible/seeds/rust/seed-049.rs +0 -26
- package/packages/crucible/seeds/rust/seed-050 2.rs +0 -23
- package/packages/crucible/seeds/rust/seed-050.rs +0 -23
- package/packages/crucible/seeds/ts/seed-001 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-001.ts +0 -32
- package/packages/crucible/seeds/ts/seed-002 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-002.ts +0 -34
- package/packages/crucible/seeds/ts/seed-003 2.ts +0 -28
- package/packages/crucible/seeds/ts/seed-003.ts +0 -28
- package/packages/crucible/seeds/ts/seed-004 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-004.ts +0 -34
- package/packages/crucible/seeds/ts/seed-005 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-005.ts +0 -32
- package/packages/crucible/seeds/ts/seed-006 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-006.ts +0 -31
- package/packages/crucible/seeds/ts/seed-007 2.ts +0 -28
- package/packages/crucible/seeds/ts/seed-007.ts +0 -28
- package/packages/crucible/seeds/ts/seed-008 2.ts +0 -40
- package/packages/crucible/seeds/ts/seed-008.ts +0 -40
- package/packages/crucible/seeds/ts/seed-009 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-009.ts +0 -31
- package/packages/crucible/seeds/ts/seed-010 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-010.ts +0 -33
- package/packages/crucible/seeds/ts/seed-011 2.ts +0 -29
- package/packages/crucible/seeds/ts/seed-011.ts +0 -29
- package/packages/crucible/seeds/ts/seed-012 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-012.ts +0 -34
- package/packages/crucible/seeds/ts/seed-013 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-013.ts +0 -31
- package/packages/crucible/seeds/ts/seed-014 2.ts +0 -36
- package/packages/crucible/seeds/ts/seed-014.ts +0 -36
- package/packages/crucible/seeds/ts/seed-015 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-015.ts +0 -31
- package/packages/crucible/seeds/ts/seed-016 2.ts +0 -37
- package/packages/crucible/seeds/ts/seed-016.ts +0 -37
- package/packages/crucible/seeds/ts/seed-017 2.ts +0 -44
- package/packages/crucible/seeds/ts/seed-017.ts +0 -44
- package/packages/crucible/seeds/ts/seed-018 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-018.ts +0 -33
- package/packages/crucible/seeds/ts/seed-019 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-019.ts +0 -32
- package/packages/crucible/seeds/ts/seed-020 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-020.ts +0 -33
- package/packages/crucible/seeds/ts/seed-021 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-021.ts +0 -33
- package/packages/crucible/seeds/ts/seed-022 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-022.ts +0 -34
- package/packages/crucible/seeds/ts/seed-023 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-023.ts +0 -33
- package/packages/crucible/seeds/ts/seed-024 2.ts +0 -35
- package/packages/crucible/seeds/ts/seed-024.ts +0 -35
- package/packages/crucible/seeds/ts/seed-025 2.ts +0 -29
- package/packages/crucible/seeds/ts/seed-025.ts +0 -29
- package/packages/crucible/seeds/ts/seed-026 2.ts +0 -36
- package/packages/crucible/seeds/ts/seed-026.ts +0 -36
- package/packages/crucible/seeds/ts/seed-027 2.ts +0 -30
- package/packages/crucible/seeds/ts/seed-027.ts +0 -30
- package/packages/crucible/seeds/ts/seed-028 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-028.ts +0 -32
- package/packages/crucible/seeds/ts/seed-029 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-029.ts +0 -34
- package/packages/crucible/seeds/ts/seed-030 2.ts +0 -37
- package/packages/crucible/seeds/ts/seed-030.ts +0 -37
- package/packages/crucible/seeds/ts/seed-031 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-031.ts +0 -31
- package/packages/crucible/seeds/ts/seed-032 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-032.ts +0 -32
- package/packages/crucible/seeds/ts/seed-033 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-033.ts +0 -32
- package/packages/crucible/seeds/ts/seed-034 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-034.ts +0 -34
- package/packages/crucible/seeds/ts/seed-035 2.ts +0 -29
- package/packages/crucible/seeds/ts/seed-035.ts +0 -29
- package/packages/crucible/seeds/ts/seed-036 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-036.ts +0 -34
- package/packages/crucible/seeds/ts/seed-037 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-037.ts +0 -33
- package/packages/crucible/seeds/ts/seed-038 2.ts +0 -29
- package/packages/crucible/seeds/ts/seed-038.ts +0 -29
- package/packages/crucible/seeds/ts/seed-039 2.ts +0 -35
- package/packages/crucible/seeds/ts/seed-039.ts +0 -35
- package/packages/crucible/seeds/ts/seed-040 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-040.ts +0 -31
- package/packages/crucible/seeds/ts/seed-041 2.ts +0 -29
- package/packages/crucible/seeds/ts/seed-041.ts +0 -29
- package/packages/crucible/seeds/ts/seed-042 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-042.ts +0 -33
- package/packages/crucible/seeds/ts/seed-043 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-043.ts +0 -32
- package/packages/crucible/seeds/ts/seed-044 2.ts +0 -36
- package/packages/crucible/seeds/ts/seed-044.ts +0 -36
- package/packages/crucible/seeds/ts/seed-045 2.ts +0 -39
- package/packages/crucible/seeds/ts/seed-045.ts +0 -39
- package/packages/crucible/seeds/ts/seed-046 2.ts +0 -41
- package/packages/crucible/seeds/ts/seed-046.ts +0 -41
- package/packages/crucible/seeds/ts/seed-047 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-047.ts +0 -33
- package/packages/crucible/seeds/ts/seed-048 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-048.ts +0 -33
- package/packages/crucible/seeds/ts/seed-049 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-049.ts +0 -34
- package/packages/crucible/seeds/ts/seed-050 2.ts +0 -41
- package/packages/crucible/seeds/ts/seed-050.ts +0 -41
- package/packages/crucible/seeds/ts/seed-051 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-051.ts +0 -34
- package/packages/crucible/seeds/ts/seed-052 2.ts +0 -36
- package/packages/crucible/seeds/ts/seed-052.ts +0 -36
- package/packages/scanner/alert-manager.js +0 -1
- package/packages/scanner/ast-analyzer.js +0 -1
- package/packages/scanner/cfg-analyzer.js +0 -1
- package/packages/scanner/code-scanner.js +0 -1
- package/packages/scanner/file-collector.js +0 -1
- package/packages/scanner/file-watcher.js +0 -1
- package/packages/scanner/ghost-code-detector.js +0 -1
- package/packages/scanner/hallucination-detector.js +0 -1
- package/packages/scanner/health-checker.js +0 -1
- package/packages/scanner/investor-report.js +0 -1
- package/packages/scanner/master-health-checker.js +0 -1
- package/packages/scanner/monitor-store.js +0 -1
- package/packages/scanner/python_ast_helper.py +0 -426
- package/packages/scanner/secret-scanner.js +0 -1
- package/packages/scanner/sentinel-core.js +0 -1
- package/packages/scanner/support-bot.js +0 -1
- package/packages/scanner/support-knowledge.js +0 -1
- package/packages/scanner/taint-tracker.js +0 -1
- /package/{packages → dist/packages}/crucible/badge-generator.js +0 -0
- /package/{packages → dist/packages}/crucible/banner.js +0 -0
- /package/{packages → dist/packages}/crucible/ci-integration.js +0 -0
- /package/{packages → dist/packages}/crucible/golden-master.js +0 -0
- /package/{packages → dist/packages}/crucible/index.js +0 -0
- /package/{packages → dist/packages}/crucible/kenny-mode.js +0 -0
- /package/{packages → dist/packages}/crucible/leaderboard.js +0 -0
- /package/{packages → dist/packages}/crucible/mutation-engine.js +0 -0
- /package/{packages → dist/packages}/crucible/pattern-learner.js +0 -0
- /package/{packages → dist/packages}/crucible/rule-loader.js +0 -0
- /package/{packages → dist/packages}/crucible/seeding-engine.js +0 -0
- /package/{packages → dist/packages}/crucible/self-attack.js +0 -0
- /package/{packages → dist/packages}/scanner/ai-confidence-scorer.js +0 -0
- /package/{packages → dist/packages}/scanner/baseline-manager.js +0 -0
- /package/{packages → dist/packages}/scanner/codebase-passport.js +0 -0
- /package/{packages → dist/packages}/scanner/copy-paste-detector.js +0 -0
- /package/{packages → dist/packages}/scanner/dependency-graph.js +0 -0
- /package/{packages → dist/packages}/scanner/drift-detector.js +0 -0
- /package/{packages → dist/packages}/scanner/executive-report.js +0 -0
- /package/{packages → dist/packages}/scanner/export-verifier.js +0 -0
- /package/{packages → dist/packages}/scanner/feedback-client.js +0 -0
- /package/{packages → dist/packages}/scanner/go-ast-analyzer.js +0 -0
- /package/{packages → dist/packages}/scanner/html-report.js +0 -0
- /package/{packages → dist/packages}/scanner/index.js +0 -0
- /package/{packages → dist/packages}/scanner/license-manager.js +0 -0
- /package/{packages → dist/packages}/scanner/monitor-notifier.js +0 -0
- /package/{packages → dist/packages}/scanner/monitor-service.js +0 -0
- /package/{packages → dist/packages}/scanner/pre-commit-gate.js +0 -0
- /package/{packages → dist/packages}/scanner/python-ast-analyzer.js +0 -0
- /package/{packages → dist/packages}/scanner/read-file.js +0 -0
- /package/{packages → dist/packages}/scanner/scan-diff.js +0 -0
- /package/{packages → dist/packages}/scanner/scan-runner.js +0 -0
- /package/{packages → dist/packages}/scanner/sentinel-knowledge.js +0 -0
- /package/{packages → dist/packages}/scanner/slack-notifier.js +0 -0
- /package/{packages → dist/packages}/scanner/tech-debt-analyzer.js +0 -0
- /package/{packages → dist/packages}/scanner/tech-debt-cost.js +0 -0
- /package/{packages → dist/packages}/scanner/widget-generator.js +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const fs=require("fs"),path=require("path"),crypto=require("crypto");class InvestorReport{constructor(e={}){this.rootPath=e.rootPath||process.cwd(),this.companyName=e.companyName||this._detectProjectName(),this.generatedAt=new Date,this.reportKey=e.reportKey||null,this.tier=this._validateKey(this.reportKey)}_validateKey(e){if(!e||"string"!=typeof e)return"free";try{const n=e.split(":");if(n.length<3)return"free";const t=n[0],s=n[1],r=n.slice(2).join(":");if(!["snapshot","full"].includes(t))return"free";const o=parseInt(s,10);if(isNaN(o)||Date.now()-o>7776e6)return"free";const a="thuban-investor-salt-2026";return r===crypto.createHmac("sha256",a).update(`thuban-investor-${t}:${s}`).digest("hex").slice(0,16)?t:"free"}catch{return"free"}}static generateKey(e="full"){const n=Date.now().toString();return`${e}:${n}:${crypto.createHmac("sha256","thuban-investor-salt-2026").update(`thuban-investor-${e}:${n}`).digest("hex").slice(0,16)}`}_detectProjectName(){try{return JSON.parse(fs.readFileSync(path.join(this.rootPath,"package.json"),"utf-8")).name||path.basename(this.rootPath)}catch{return path.basename(this.rootPath)}}generate(e){const{scanResults:n={},hallResults:t={},debtCost:s={},ghostResults:r={},aiScoreResults:o={},cloneResults:a={},passportData:i={},fileCount:l=0,lineCount:d=0}=e,c=`THB-INV-${Date.now().toString(36).toUpperCase()}`,m=this._calculateOverallScore(e),u=this._scoreToGrade(m),g=this._gradeColor(u);return this._renderHTML({reportId:c,score:m,grade:u,gradeColor:g,scanResults:n,hallResults:t,debtCost:s,ghostResults:r,aiScoreResults:o,cloneResults:a,passportData:i,fileCount:l,lineCount:d,tier:this.tier})}_calculateOverallScore(e){let n=100;const t=e.hallResults||{},s=e.ghostResults||{},r=e.cloneResults||{},o=e.aiScoreResults||{},a=e.scanResults||{};n-=15*(t.phantomAPIs?.length||0),n-=5*(t.deprecatedAPIs?.length||0),n-=2*(s.totalGhosts||0),n-=3*(r.totalClusters||0),n-=1*(o.aiLikelyCount||0);let i=0;if(a&&"object"==typeof a)for(const[,e]of Object.entries(a))e?.issues&&(i+=e.issues.length);return n-=Math.min(.5*i,30),Math.max(0,Math.min(100,Math.round(n)))}_scoreToGrade(e){return e>=90?"A":e>=80?"B":e>=65?"C":e>=50?"D":"F"}_gradeColor(e){return{A:"#00ff88",B:"#88ff00",C:"#ffd93d",D:"#ff8844",F:"#ff4444"}[e]||"#ff4444"}_investmentVerdict(e){return e>=80?{label:"PASS — Low Risk Investment",color:"#00ff88",bg:"rgba(0,255,136,0.1)",border:"rgba(0,255,136,0.3)"}:e>=65?{label:"CONDITIONAL PASS — Moderate Risk, Remediation Required",color:"#ffd93d",bg:"rgba(255,217,61,0.1)",border:"rgba(255,217,61,0.3)"}:e>=50?{label:"HIGH RISK — Significant Technical Debt",color:"#ff8844",bg:"rgba(255,136,68,0.1)",border:"rgba(255,136,68,0.3)"}:{label:"DO NOT INVEST — Critical Code Quality Issues",color:"#ff4444",bg:"rgba(255,68,68,0.1)",border:"rgba(255,68,68,0.3)"}}_aiDependencyAssessment(e){return e<10?{level:"Minimal",description:"Minimal AI dependency — traditional development team",color:"#00ff88"}:e<30?{level:"Moderate",description:"Moderate AI usage — within normal range for modern development",color:"#ffd93d"}:e<60?{level:"Heavy",description:"Heavy AI dependency — verify team can maintain without AI tools",color:"#ff8844"}:{level:"AI-Dominant",description:"AI-dominant codebase — high bus-factor risk if AI tools become unavailable",color:"#ff4444"}}_buildRemediationEstimate(e){const n=[],t=e.hallResults||{},s=e.ghostResults||{},r=e.cloneResults||{},o=e.aiScoreResults||{},a=t.phantomAPIs?.length||0,i=t.deprecatedAPIs?.length||0,l=s.totalGhosts||0,d=r.totalClusters||0,c=o.aiLikelyCount||0;if(a>0){const e=2*a;n.push({category:"Hallucinated APIs",issues:a,hours:e,cost80:80*e,cost120:120*e,priority:"Critical"})}if(i>0){const e=Math.ceil(1.5*i);n.push({category:"Deprecated APIs",issues:i,hours:e,cost80:80*e,cost120:120*e,priority:"High"})}if(l>0){const e=Math.ceil(.5*l);n.push({category:"Ghost / Dead Code",issues:l,hours:e,cost80:80*e,cost120:120*e,priority:"Medium"})}if(d>0){const e=3*d;n.push({category:"Code Clones / Duplication",issues:d,hours:e,cost80:80*e,cost120:120*e,priority:"Medium"})}if(c>0){const e=1*c;n.push({category:"AI-Generated Code Review",issues:c,hours:e,cost80:80*e,cost120:120*e,priority:"Low"})}let m=0;const u=e.scanResults||{};if(u&&"object"==typeof u)for(const[,e]of Object.entries(u))e?.issues&&(m+=e.issues.length);if(m>0){const e=Math.ceil(.3*m);n.push({category:"Code Quality Issues",issues:m,hours:e,cost80:80*e,cost120:120*e,priority:"Low"})}return n}_assessTeamCompetency(e){const n=e.scanResults||{},t=e.ghostResults||{},s=(e.cloneResults,e.aiScoreResults,e.lineCount,e.fileCount||1);let r=0,o=0;if(n&&"object"==typeof n)for(const[,e]of Object.entries(n))if(e?.issues){o+=e.issues.length;for(const n of e.issues){const e=(n.message||n.rule||"").toLowerCase();(e.includes("error")||e.includes("catch")||e.includes("exception")||e.includes("try"))&&r++}}const a=o>0?1-r/o:1,i=o/s,l=t.wastedPercent||0,d=(e.testFileCount||0)/s,c=e.commentRatio||0,m=[];return a>=.9?m.push({name:"Error Handling Patterns",rating:"Strong",color:"#00ff88"}):a>=.7?m.push({name:"Error Handling Patterns",rating:"Adequate",color:"#ffd93d"}):a>=.4?m.push({name:"Error Handling Patterns",rating:"Needs Improvement",color:"#ff8844"}):m.push({name:"Error Handling Patterns",rating:"Concerning",color:"#ff4444"}),i<=1?m.push({name:"Naming Consistency",rating:"Strong",color:"#00ff88"}):i<=3?m.push({name:"Naming Consistency",rating:"Adequate",color:"#ffd93d"}):i<=6?m.push({name:"Naming Consistency",rating:"Needs Improvement",color:"#ff8844"}):m.push({name:"Naming Consistency",rating:"Concerning",color:"#ff4444"}),l<=3?m.push({name:"Function Size Distribution",rating:"Strong",color:"#00ff88"}):l<=8?m.push({name:"Function Size Distribution",rating:"Adequate",color:"#ffd93d"}):l<=15?m.push({name:"Function Size Distribution",rating:"Needs Improvement",color:"#ff8844"}):m.push({name:"Function Size Distribution",rating:"Concerning",color:"#ff4444"}),d>=.3?m.push({name:"Test Coverage Indicators",rating:"Strong",color:"#00ff88"}):d>=.15?m.push({name:"Test Coverage Indicators",rating:"Adequate",color:"#ffd93d"}):d>=.05?m.push({name:"Test Coverage Indicators",rating:"Needs Improvement",color:"#ff8844"}):m.push({name:"Test Coverage Indicators",rating:"Concerning",color:"#ff4444"}),c>=.15?m.push({name:"Documentation Quality",rating:"Strong",color:"#00ff88"}):c>=.08?m.push({name:"Documentation Quality",rating:"Adequate",color:"#ffd93d"}):c>=.03?m.push({name:"Documentation Quality",rating:"Needs Improvement",color:"#ff8844"}):m.push({name:"Documentation Quality",rating:"Concerning",color:"#ff4444"}),m}_buildExecutiveSummary(e,n){const t=n.hallResults||{},s=n.ghostResults||{},r=n.aiScoreResults||{},o=t.phantomAPIs?.length||0,a=s.totalGhosts||0,i=r.aiPercentage||0,l=this._buildRemediationEstimate(n),d=l.reduce((e,n)=>e+n.hours,0),c=l.reduce((e,n)=>e+n.cost80,0);let m;m=e>=80?"demonstrates strong engineering practices":e>=65?"demonstrates competent engineering practices with areas requiring attention":e>=50?"shows foundational engineering capability but carries significant technical debt":"exhibits critical code quality deficiencies that pose material risk";let u=[`This codebase ${m} with a trust score of ${e}/100.`];return o>0?u.push(`${o} critical AI-hallucinated API call${o>1?"s":""} require${1===o?"s":""} immediate remediation (estimated ${2*o} dev-hours).`):a>0&&u.push(`${a} dead code function${a>1?"s":""} should be removed to reduce maintenance surface area.`),i>30?u.push(`${i}% of the codebase shows AI-generation signals, indicating elevated dependency on AI tooling.`):e>=65?u.push("The development team shows strong architectural discipline with manageable technical debt."):u.push("The development team would benefit from structured code review processes and automated quality gates."),d>0&&u.push(`Estimated remediation cost to reach investment-grade: £${c.toLocaleString()}.`),u.join(" ")}_buildRiskMatrix(e){const n=e.hallResults||{},t=e.ghostResults||{},s=e.cloneResults||{},r=e.scanResults||{},o=n.phantomAPIs?.length||0,a=n.deprecatedAPIs?.length||0,i=t.totalGhosts||0,l=s.totalClusters||0;let d=0,c=0;if(r&&"object"==typeof r)for(const[,e]of Object.entries(r))if(e?.issues)for(const n of e.issues){const e=(n.message||n.rule||"").toLowerCase();(e.includes("inject")||e.includes("sql")||e.includes("xss")||e.includes("taint"))&&d++,(e.includes("style")||e.includes("format")||e.includes("indent")||e.includes("naming"))&&c++}return{criticalLikely:{items:[],count:o+d},criticalUnlikely:{items:[],count:0},moderateLikely:{items:[],count:i+l},moderateUnlikely:{items:[],count:a+c},phantomCount:o,injectionCount:d,ghostCount:i,cloneCount:l,deprecatedCount:a,styleIssueCount:c}}_renderHTML(e){const n=this.generatedAt,t=n.toLocaleDateString("en-GB",{day:"numeric",month:"long",year:"numeric"}),s=n.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}),r=e.hallResults.phantomAPIs?.length||0,o=e.hallResults.deprecatedAPIs?.length||0,a=e.ghostResults.totalGhosts||0,i=e.ghostResults.totalWastedLines||0,l=(e.cloneResults.totalClusters,e.cloneResults.totalDuplicateLines,e.aiScoreResults.aiLikelyCount||0),d=e.aiScoreResults.aiPossibleCount||0,c=e.aiScoreResults.aiPercentage||0,m=e.debtCost.totalHoursManual||0,u=e.debtCost.totalCostManual||0,g=e.debtCost.totalHoursThuban||0,h=e.debtCost.totalSaving||0,p=e.debtCost.savingPercent||0,v=this._investmentVerdict(e.score),f=this._aiDependencyAssessment(c),b=this._buildExecutiveSummary(e.score,{hallResults:e.hallResults,ghostResults:e.ghostResults,aiScoreResults:e.aiScoreResults,debtCost:e.debtCost,scanResults:e.scanResults,fileCount:e.fileCount,lineCount:e.lineCount}),y=this._buildRemediationEstimate({hallResults:e.hallResults,ghostResults:e.ghostResults,aiScoreResults:e.aiScoreResults,cloneResults:e.cloneResults,scanResults:e.scanResults}),x=y.reduce((e,n)=>e+n.hours,0),C=y.reduce((e,n)=>e+n.cost80,0),w=y.reduce((e,n)=>e+n.cost120,0),$=y.reduce((e,n)=>e+n.issues,0),R=this._buildRiskMatrix({hallResults:e.hallResults,ghostResults:e.ghostResults,cloneResults:e.cloneResults,scanResults:e.scanResults}),k=this._assessTeamCompetency({scanResults:e.scanResults,ghostResults:e.ghostResults,cloneResults:e.cloneResults,aiScoreResults:e.aiScoreResults,fileCount:e.fileCount,lineCount:e.lineCount,testFileCount:e.passportData?.testFileCount||0,commentRatio:e.passportData?.commentRatio||0});let I="";if(e.hallResults.phantomAPIs)for(const n of e.hallResults.phantomAPIs.slice(0,8))I+=`<tr>\n <td class="sev-critical">CRITICAL</td>\n <td>${this._esc(n.file||"")}:${n.line||"?"}</td>\n <td>${this._esc(n.name||n.code||"Phantom API")}</td>\n <td>Will crash at runtime — method does not exist</td>\n </tr>`;if(e.hallResults.deprecatedAPIs)for(const n of e.hallResults.deprecatedAPIs.slice(0,5))I+=`<tr>\n <td class="sev-high">HIGH</td>\n <td>${this._esc(n.file||"")}:${n.line||"?"}</td>\n <td>${this._esc(n.name||n.code||"Deprecated API")}</td>\n <td>Deprecated — will break in future versions</td>\n </tr>`;let A="";if(e.ghostResults.ghosts)for(const n of e.ghostResults.ghosts.slice(0,8))A+=`<tr>\n <td>${this._esc(n.file)}:${n.line}</td>\n <td>${this._esc(n.name)}()</td>\n <td>${n.wastedLines} lines</td>\n <td>${n.references} references</td>\n </tr>`;let S="";for(const e of y){const n="Critical"===e.priority?"var(--red)":"High"===e.priority?"var(--yellow)":"Medium"===e.priority?"var(--cyan)":"var(--dim)";S+=`<tr>\n <td>${this._esc(e.category)}</td>\n <td style="text-align:center">${e.issues}</td>\n <td style="text-align:center">${e.hours}</td>\n <td style="text-align:right">£${e.cost80.toLocaleString()}</td>\n <td style="text-align:right">£${e.cost120.toLocaleString()}</td>\n <td style="color:${n}; font-weight:600">${e.priority}</td>\n </tr>`}let z="";for(const e of k)z+=`<tr>\n <td>${this._esc(e.name)}</td>\n <td style="color:${e.color}; font-weight:600">${e.rating}</td>\n </tr>`;const T=[{label:"Pre-seed typical",min:40,max:55},{label:"Seed typical",min:50,max:65},{label:"Series A typical",min:60,max:75},{label:"Series B typical",min:70,max:80},{label:"Series C+",min:80,max:90}];let P="";for(const n of T)P+=`\n <div class="benchmark-row">\n <div class="benchmark-label">${n.label}</div>\n <div class="benchmark-track">\n <div class="benchmark-range" style="left:${n.min}%; width:${n.max-n.min}%"></div>\n <div class="benchmark-marker" style="left:${e.score}%" title="This codebase: ${e.score}"></div>\n </div>\n <div class="benchmark-values">${n.min}–${n.max}</div>\n </div>`;return`<!DOCTYPE html>\n<html lang="en">\n<head>\n<meta charset="UTF-8">\n<meta name="viewport" content="width=device-width, initial-scale=1.0">\n<title>Thuban Investor Due Diligence Report — ${this._esc(this.companyName)}</title>\n<style>\n @page { size: A4; margin: 15mm; }\n @media print {\n body { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }\n .no-print { display: none !important; }\n .page-break { page-break-before: always; }\n .verdict-banner { break-inside: avoid; }\n }\n\n :root {\n --bg: #0a0a1a;\n --surface: #12122a;\n --border: #2a2a5a;\n --text: #e0e0f0;\n --dim: #8888aa;\n --cyan: #00f6ff;\n --green: #00ff88;\n --yellow: #ffd93d;\n --red: #ff4444;\n --purple: #a855f7;\n --orange: #ff8844;\n --mono: 'JetBrains Mono', 'Cascadia Code', 'Consolas', monospace;\n --sans: 'Segoe UI', system-ui, -apple-system, sans-serif;\n }\n\n * { margin: 0; padding: 0; box-sizing: border-box; }\n\n body {\n background: var(--bg);\n color: var(--text);\n font-family: var(--sans);\n font-size: 11pt;\n line-height: 1.5;\n max-width: 210mm;\n margin: 0 auto;\n padding: 20mm 15mm;\n }\n\n /* Header */\n .report-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n border-bottom: 2px solid var(--cyan);\n padding-bottom: 1.5rem;\n margin-bottom: 2rem;\n }\n\n .report-header .logo {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n }\n\n .report-header .logo svg { width: 36px; height: 36px; }\n\n .report-header .logo-text {\n font-size: 1.5rem;\n font-weight: 300;\n letter-spacing: 0.3em;\n color: var(--cyan);\n }\n\n .report-header .meta {\n text-align: right;\n font-size: 0.8rem;\n color: var(--dim);\n line-height: 1.8;\n }\n\n .report-title {\n text-align: center;\n margin-bottom: 2rem;\n }\n\n .report-title h1 {\n font-size: 1.8rem;\n font-weight: 700;\n margin-bottom: 0.25rem;\n }\n\n .report-title .subtitle {\n font-size: 0.85rem;\n color: var(--dim);\n text-transform: uppercase;\n letter-spacing: 0.15em;\n margin-bottom: 0.25rem;\n }\n\n .report-title .project-name {\n color: var(--cyan);\n font-size: 1.1rem;\n font-family: var(--mono);\n }\n\n /* Verdict Banner */\n .verdict-banner {\n text-align: center;\n padding: 1.5rem 2rem;\n border-radius: 12px;\n margin-bottom: 2rem;\n font-size: 1.3rem;\n font-weight: 700;\n letter-spacing: 0.05em;\n }\n\n /* Executive Summary */\n .exec-summary {\n background: var(--surface);\n border: 1px solid var(--border);\n border-radius: 12px;\n padding: 1.5rem 2rem;\n margin-bottom: 2rem;\n font-size: 0.9rem;\n line-height: 1.7;\n color: var(--text);\n }\n\n .exec-summary .summary-label {\n font-size: 0.7rem;\n text-transform: uppercase;\n letter-spacing: 0.1em;\n color: var(--dim);\n margin-bottom: 0.5rem;\n font-weight: 600;\n }\n\n /* Score Ring */\n .score-section {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 3rem;\n margin-bottom: 2.5rem;\n padding: 2rem;\n background: var(--surface);\n border: 1px solid var(--border);\n border-radius: 12px;\n }\n\n .score-ring {\n position: relative;\n width: 140px;\n height: 140px;\n }\n\n .score-ring svg { transform: rotate(-90deg); }\n\n .score-ring .score-value {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n }\n\n .score-ring .grade {\n font-size: 2.5rem;\n font-weight: 700;\n font-family: var(--mono);\n line-height: 1;\n }\n\n .score-ring .number {\n font-size: 0.85rem;\n color: var(--dim);\n }\n\n .score-summary { flex: 1; }\n\n .score-summary h2 {\n font-size: 1.3rem;\n margin-bottom: 0.75rem;\n }\n\n .stat-row {\n display: flex;\n gap: 2rem;\n flex-wrap: wrap;\n margin-top: 1rem;\n }\n\n .stat {\n text-align: center;\n min-width: 80px;\n }\n\n .stat .stat-value {\n font-size: 1.5rem;\n font-weight: 700;\n font-family: var(--mono);\n }\n\n .stat .stat-label {\n font-size: 0.7rem;\n color: var(--dim);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n .stat-critical .stat-value { color: var(--red); }\n .stat-warning .stat-value { color: var(--yellow); }\n .stat-good .stat-value { color: var(--green); }\n .stat-info .stat-value { color: var(--cyan); }\n\n /* Sections */\n .section {\n margin-bottom: 2rem;\n }\n\n .section-header {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 1rem;\n padding-bottom: 0.5rem;\n border-bottom: 1px solid var(--border);\n }\n\n .section-header h3 {\n font-size: 1rem;\n font-weight: 600;\n }\n\n .section-header .icon { font-size: 1.2rem; }\n\n /* Tables */\n table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.8rem;\n margin-bottom: 1rem;\n }\n\n th {\n text-align: left;\n padding: 0.5rem;\n background: var(--surface);\n border-bottom: 1px solid var(--border);\n font-weight: 600;\n font-size: 0.7rem;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--dim);\n }\n\n td {\n padding: 0.4rem 0.5rem;\n border-bottom: 1px solid rgba(42,42,90,0.3);\n font-family: var(--mono);\n font-size: 0.75rem;\n word-break: break-all;\n }\n\n .sev-critical { color: var(--red); font-weight: 700; }\n .sev-high { color: var(--yellow); font-weight: 600; }\n\n /* Risk Matrix */\n .risk-matrix {\n display: grid;\n grid-template-columns: auto 1fr 1fr;\n grid-template-rows: auto 1fr 1fr;\n gap: 0;\n margin-bottom: 1rem;\n border: 1px solid var(--border);\n border-radius: 12px;\n overflow: hidden;\n }\n\n .risk-matrix .rm-corner {\n background: var(--surface);\n padding: 0.5rem;\n }\n\n .risk-matrix .rm-col-header {\n background: var(--surface);\n padding: 0.6rem 0.75rem;\n text-align: center;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--dim);\n border-bottom: 1px solid var(--border);\n }\n\n .risk-matrix .rm-row-header {\n background: var(--surface);\n padding: 0.6rem 0.75rem;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--dim);\n display: flex;\n align-items: center;\n border-right: 1px solid var(--border);\n }\n\n .risk-matrix .rm-cell {\n padding: 0.75rem;\n font-size: 0.75rem;\n border-right: 1px solid rgba(42,42,90,0.3);\n border-bottom: 1px solid rgba(42,42,90,0.3);\n }\n\n .rm-cell-critical-likely { background: rgba(255,68,68,0.12); }\n .rm-cell-critical-unlikely { background: rgba(255,136,68,0.08); }\n .rm-cell-moderate-likely { background: rgba(255,217,61,0.08); }\n .rm-cell-moderate-unlikely { background: rgba(0,246,255,0.05); }\n\n .rm-cell .rm-count {\n font-family: var(--mono);\n font-size: 1.2rem;\n font-weight: 700;\n margin-bottom: 0.25rem;\n }\n\n .rm-cell .rm-items {\n font-size: 0.7rem;\n color: var(--dim);\n line-height: 1.4;\n }\n\n /* AI Dependency */\n .ai-dep-bar {\n background: var(--surface);\n border: 1px solid var(--border);\n border-radius: 12px;\n padding: 1.5rem 2rem;\n margin-bottom: 1rem;\n }\n\n .ai-dep-meter {\n height: 24px;\n background: rgba(42,42,90,0.5);\n border-radius: 12px;\n position: relative;\n margin: 1rem 0;\n overflow: visible;\n }\n\n .ai-dep-fill {\n height: 100%;\n border-radius: 12px;\n transition: width 0.3s;\n }\n\n .ai-dep-zones {\n display: flex;\n justify-content: space-between;\n font-size: 0.65rem;\n color: var(--dim);\n margin-top: 0.5rem;\n }\n\n .ai-dep-assessment {\n margin-top: 1rem;\n font-size: 0.85rem;\n line-height: 1.6;\n }\n\n /* Cost Box */\n .cost-box {\n background: var(--surface);\n border: 1px solid var(--border);\n border-radius: 12px;\n padding: 1.5rem 2rem;\n margin-bottom: 1rem;\n }\n\n .cost-grid {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n gap: 1.5rem;\n text-align: center;\n }\n\n .cost-item .cost-value {\n font-size: 1.8rem;\n font-weight: 700;\n font-family: var(--mono);\n }\n\n .cost-item .cost-label {\n font-size: 0.75rem;\n color: var(--dim);\n margin-top: 0.25rem;\n }\n\n .cost-manual .cost-value { color: var(--red); }\n .cost-thuban .cost-value { color: var(--cyan); }\n .cost-saving .cost-value { color: var(--green); }\n\n /* Benchmarks */\n .benchmark-row {\n display: flex;\n align-items: center;\n gap: 1rem;\n margin-bottom: 0.75rem;\n }\n\n .benchmark-label {\n width: 130px;\n font-size: 0.75rem;\n color: var(--dim);\n text-align: right;\n flex-shrink: 0;\n }\n\n .benchmark-track {\n flex: 1;\n height: 20px;\n background: rgba(42,42,90,0.4);\n border-radius: 10px;\n position: relative;\n }\n\n .benchmark-range {\n position: absolute;\n top: 3px;\n height: 14px;\n background: rgba(0,246,255,0.15);\n border: 1px solid rgba(0,246,255,0.3);\n border-radius: 7px;\n }\n\n .benchmark-marker {\n position: absolute;\n top: -2px;\n width: 4px;\n height: 24px;\n background: var(--cyan);\n border-radius: 2px;\n box-shadow: 0 0 8px rgba(0,246,255,0.5);\n transform: translateX(-2px);\n }\n\n .benchmark-values {\n width: 50px;\n font-size: 0.7rem;\n color: var(--dim);\n font-family: var(--mono);\n flex-shrink: 0;\n }\n\n /* Team Competency */\n .competency-table td:first-child {\n font-family: var(--sans);\n font-size: 0.8rem;\n word-break: normal;\n }\n\n .competency-table td:last-child {\n text-align: center;\n font-size: 0.8rem;\n width: 140px;\n }\n\n /* Callouts */\n .callout {\n padding: 1rem 1.5rem;\n border-radius: 8px;\n margin-bottom: 1rem;\n font-size: 0.85rem;\n }\n\n .callout-danger {\n background: rgba(255,68,68,0.08);\n border: 1px solid rgba(255,68,68,0.2);\n color: #ffaaaa;\n }\n\n .callout-warning {\n background: rgba(255,217,61,0.08);\n border: 1px solid rgba(255,217,61,0.2);\n color: #ffe088;\n }\n\n /* Paywall Gate */\n .paywall-section { position: relative; }\n .paywall-overlay {\n padding: 3rem 2rem;\n text-align: center;\n background: linear-gradient(135deg, rgba(18,18,42,0.95), rgba(10,10,26,0.98));\n border: 1px dashed var(--border);\n border-radius: 12px;\n }\n .paywall-message { max-width: 420px; margin: 0 auto; }\n .paywall-message h4 { font-size: 1.1rem; }\n .paywall-message code {\n background: rgba(0,246,255,0.1);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 0.8rem;\n }\n .paywall-message a { text-decoration: none; }\n .paywall-message a:hover { text-decoration: underline; }\n\n /* Confidentiality Footer */\n .confidentiality {\n margin-top: 3rem;\n padding: 1.25rem 1.5rem;\n background: var(--surface);\n border: 1px solid var(--border);\n border-radius: 8px;\n font-size: 0.7rem;\n color: var(--dim);\n line-height: 1.6;\n text-align: center;\n }\n\n .confidentiality strong {\n color: var(--yellow);\n letter-spacing: 0.1em;\n }\n\n /* Footer */\n .report-footer {\n margin-top: 1.5rem;\n padding-top: 1.5rem;\n border-top: 1px solid var(--border);\n display: flex;\n justify-content: space-between;\n font-size: 0.75rem;\n color: var(--dim);\n }\n\n .report-footer a { color: var(--cyan); text-decoration: none; }\n\n /* Print button */\n .print-btn {\n position: fixed;\n bottom: 2rem;\n right: 2rem;\n background: var(--cyan);\n color: var(--bg);\n border: none;\n padding: 0.75rem 1.5rem;\n border-radius: 8px;\n font-weight: 600;\n font-size: 0.9rem;\n cursor: pointer;\n box-shadow: 0 4px 20px rgba(0,246,255,0.3);\n z-index: 100;\n }\n\n .print-btn:hover { background: #33f8ff; }\n\n /* Totals row */\n .totals-row td {\n font-weight: 700;\n border-top: 2px solid var(--border);\n padding-top: 0.6rem;\n }\n\n /* Responsive */\n @media screen and (max-width: 700px) {\n body { padding: 1rem; }\n .cost-grid { grid-template-columns: 1fr; }\n .stat-row { flex-direction: column; gap: 0.75rem; }\n .score-section { flex-direction: column; gap: 1.5rem; }\n .risk-matrix { grid-template-columns: auto 1fr; }\n .benchmark-label { width: 80px; font-size: 0.65rem; }\n }\n</style>\n</head>\n<body>\n\n<button class="print-btn no-print" onclick="window.print()">Save as PDF</button>\n\n\x3c!-- Header --\x3e\n<div class="report-header">\n <div class="logo">\n <svg viewBox="0 0 32 32" fill="none">\n <polygon points="16,2 30,28 2,28" stroke="#00f6ff" stroke-width="2" fill="none"/>\n <polygon points="16,8 25,25 7,25" stroke="#00f6ff" stroke-width="1" fill="rgba(0,246,255,0.1)"/>\n <circle cx="16" cy="18" r="3" fill="#00f6ff"/>\n </svg>\n <span class="logo-text">THUBAN</span>\n </div>\n <div class="meta">\n Report ID: ${e.reportId}<br>\n Generated: ${t} at ${s}<br>\n Engine: Thuban Code Health v0.3.0<br>\n Classification: Investor Due Diligence\n </div>\n</div>\n\n\x3c!-- Title --\x3e\n<div class="report-title">\n <div class="subtitle">Investor Due Diligence Report</div>\n <h1>Code Health Assessment</h1>\n <div class="project-name">${this._esc(this.companyName)}</div>\n</div>\n\n\x3c!-- Investment Verdict Banner --\x3e\n<div class="verdict-banner" style="background:${v.bg}; border:2px solid ${v.border}; color:${v.color}">\n ${v.label}\n</div>\n\n\x3c!-- Executive Summary --\x3e\n<div class="exec-summary">\n <div class="summary-label">Executive Summary</div>\n ${b}\n</div>\n\n\x3c!-- Score --\x3e\n<div class="score-section">\n <div class="score-ring">\n <svg width="140" height="140" viewBox="0 0 140 140">\n <circle cx="70" cy="70" r="60" fill="none" stroke="${e.gradeColor}22" stroke-width="10"/>\n <circle cx="70" cy="70" r="60" fill="none" stroke="${e.gradeColor}" stroke-width="10"\n stroke-dasharray="${Math.round(3.77*e.score)} 377"\n stroke-linecap="round"/>\n </svg>\n <div class="score-value">\n <div class="grade" style="color:${e.gradeColor}">${e.grade}</div>\n <div class="number">${e.score}/100</div>\n </div>\n </div>\n <div class="score-summary">\n <h2>Trust Score: ${"A"===e.grade?"Excellent":"B"===e.grade?"Good":"C"===e.grade?"Needs Attention":"D"===e.grade?"At Risk":"Critical"}</h2>\n <div class="stat-row">\n <div class="stat stat-info">\n <div class="stat-value">${e.fileCount.toLocaleString()}</div>\n <div class="stat-label">Files Scanned</div>\n </div>\n <div class="stat stat-info">\n <div class="stat-value">${e.lineCount.toLocaleString()}</div>\n <div class="stat-label">Lines of Code</div>\n </div>\n <div class="stat ${r>0?"stat-critical":"stat-good"}">\n <div class="stat-value">${r}</div>\n <div class="stat-label">Hallucinated APIs</div>\n </div>\n <div class="stat ${a>0?"stat-warning":"stat-good"}">\n <div class="stat-value">${a}</div>\n <div class="stat-label">Ghost Functions</div>\n </div>\n <div class="stat ${l>0?"stat-warning":"stat-good"}">\n <div class="stat-value">${c}%</div>\n <div class="stat-label">AI-Generated</div>\n </div>\n </div>\n </div>\n</div>\n\n${r>0?`\n<div class="callout callout-danger">\n <strong>MATERIAL RISK:</strong> ${r} API call${r>1?"s":""} in this codebase reference${1===r?"s":""} methods that do not exist.\n These will throw runtime errors in production. This represents a direct threat to service reliability and customer trust.\n</div>\n`:""}\n\n\x3c!-- Risk Matrix --\x3e\n${"free"===e.tier?'\n<div class="section paywall-section">\n <div class="section-header">\n <span class="icon">⚠</span>\n <h3>Risk Matrix</h3>\n </div>\n <div class="paywall-overlay">\n <div class="paywall-message">\n <div style="font-size:2rem;margin-bottom:0.75rem;">🔒</div>\n <h4 style="margin-bottom:0.5rem;color:var(--text);">Unlock Full Risk Analysis</h4>\n <p style="color:var(--dim);font-size:0.85rem;margin-bottom:1rem;">Risk Matrix, AI Dependency Assessment, and detailed findings are available with a Snapshot ($99) or Full Audit ($399) report key.</p>\n <div style="font-family:var(--mono);font-size:0.8rem;color:var(--cyan);background:rgba(0,246,255,0.05);padding:0.75rem 1rem;border-radius:8px;border:1px solid rgba(0,246,255,0.15);">\n Purchase at <a href="https://thuban.dev/#investors" style="color:var(--cyan)">thuban.dev</a> → run with <code>--key=YOUR_KEY</code>\n </div>\n </div>\n </div>\n</div>\n':`\n<div class="section">\n <div class="section-header">\n <span class="icon">⚠</span>\n <h3>Risk Matrix</h3>\n </div>\n <div class="risk-matrix">\n <div class="rm-corner"></div>\n <div class="rm-col-header" style="border-left:1px solid var(--border)">Likely</div>\n <div class="rm-col-header">Unlikely</div>\n\n <div class="rm-row-header">Critical</div>\n <div class="rm-cell rm-cell-critical-likely" style="border-left:1px solid rgba(42,42,90,0.3)">\n <div class="rm-count" style="color:var(--red)">${R.phantomCount+R.injectionCount}</div>\n <div class="rm-items">\n ${R.phantomCount>0?`${R.phantomCount} hallucinated API${R.phantomCount>1?"s":""}<br>`:""}\n ${R.injectionCount>0?`${R.injectionCount} injection risk${R.injectionCount>1?"s":""}`:""}\n ${0===R.phantomCount&&0===R.injectionCount?"None detected":""}\n </div>\n </div>\n <div class="rm-cell rm-cell-critical-unlikely">\n <div class="rm-count" style="color:var(--orange)">0</div>\n <div class="rm-items">Complex taint paths<br>(not yet assessed)</div>\n </div>\n\n <div class="rm-row-header" style="border-top:1px solid var(--border)">Moderate</div>\n <div class="rm-cell rm-cell-moderate-likely" style="border-left:1px solid rgba(42,42,90,0.3)">\n <div class="rm-count" style="color:var(--yellow)">${R.ghostCount+R.cloneCount}</div>\n <div class="rm-items">\n ${R.ghostCount>0?`${R.ghostCount} ghost/dead code<br>`:""}\n ${R.cloneCount>0?`${R.cloneCount} code clone${R.cloneCount>1?"s":""}`:""}\n ${0===R.ghostCount&&0===R.cloneCount?"None detected":""}\n </div>\n </div>\n <div class="rm-cell rm-cell-moderate-unlikely">\n <div class="rm-count" style="color:var(--cyan)">${R.deprecatedCount+R.styleIssueCount}</div>\n <div class="rm-items">\n ${R.deprecatedCount>0?`${R.deprecatedCount} deprecated API${R.deprecatedCount>1?"s":""}<br>`:""}\n ${R.styleIssueCount>0?`${R.styleIssueCount} style issue${R.styleIssueCount>1?"s":""}`:""}\n ${0===R.deprecatedCount&&0===R.styleIssueCount?"None detected":""}\n </div>\n </div>\n </div>\n</div>\n`}\n\n\x3c!-- AI Dependency Assessment --\x3e\n${"free"===e.tier?"":`\n<div class="section">\n <div class="section-header">\n <span class="icon">🤖</span>\n <h3>AI Dependency Assessment</h3>\n </div>\n <div class="ai-dep-bar">\n <div style="display:flex; justify-content:space-between; align-items:baseline; margin-bottom:0.5rem;">\n <span style="font-size:0.85rem; color:var(--dim)">AI-Generated Code Percentage</span>\n <span style="font-family:var(--mono); font-size:1.2rem; font-weight:700; color:${f.color}">${c}%</span>\n </div>\n <div class="ai-dep-meter">\n <div class="ai-dep-fill" style="width:${Math.min(c,100)}%; background:${f.color}; opacity:0.7"></div>\n </div>\n <div class="ai-dep-zones">\n <span><10% Minimal</span>\n <span>10-30% Moderate</span>\n <span>30-60% Heavy</span>\n <span>>60% Dominant</span>\n </div>\n <div class="ai-dep-assessment">\n <strong style="color:${f.color}">${f.level}:</strong> ${f.description}\n </div>\n ${l>0?`<div style="margin-top:0.75rem; font-size:0.8rem; color:var(--dim)">\n ${l} function${l>1?"s":""} flagged as high-confidence AI-generated, ${d} flagged as possible.\n These should be reviewed for correctness, edge-case handling, and adequate test coverage.\n </div>`:""}\n </div>\n</div>\n`}\n\n<div class="page-break"></div>\n\n\x3c!-- Remediation Estimate --\x3e\n${"full"!==e.tier?'\n<div class="section paywall-section">\n <div class="section-header">\n <span class="icon">💰</span>\n <h3>Remediation Cost Estimate</h3>\n </div>\n <div class="paywall-overlay">\n <div class="paywall-message">\n <div style="font-size:2rem;margin-bottom:0.75rem;">🔒</div>\n <h4 style="margin-bottom:0.5rem;color:var(--text);">Full Audit Required</h4>\n <p style="color:var(--dim);font-size:0.85rem;margin-bottom:1rem;">Remediation cost estimates, team competency analysis, and comparable benchmarks are available with a Full Audit report key ($399).</p>\n <div style="font-family:var(--mono);font-size:0.8rem;color:var(--cyan);background:rgba(0,246,255,0.05);padding:0.75rem 1rem;border-radius:8px;border:1px solid rgba(0,246,255,0.15);">\n Purchase at <a href="https://thuban.dev/#investors" style="color:var(--cyan)">thuban.dev</a> → run with <code>--key=YOUR_KEY</code>\n </div>\n </div>\n </div>\n</div>\n':`\n<div class="section">\n <div class="section-header">\n <span class="icon">💰</span>\n <h3>Remediation Cost Estimate</h3>\n </div>\n ${y.length>0?`\n <table>\n <thead>\n <tr>\n <th>Category</th>\n <th style="text-align:center">Issues</th>\n <th style="text-align:center">Est. Hours</th>\n <th style="text-align:right">Cost @ £80/hr</th>\n <th style="text-align:right">Cost @ £120/hr</th>\n <th>Priority</th>\n </tr>\n </thead>\n <tbody>\n ${S}\n <tr class="totals-row">\n <td style="font-family:var(--sans)"><strong>TOTAL</strong></td>\n <td style="text-align:center">${$}</td>\n <td style="text-align:center">${x}</td>\n <td style="text-align:right; color:var(--yellow)">£${C.toLocaleString()}</td>\n <td style="text-align:right; color:var(--red)">£${w.toLocaleString()}</td>\n <td></td>\n </tr>\n </tbody>\n </table>\n <div style="font-size:0.8rem; color:var(--dim); margin-top:0.5rem;">\n Estimates based on industry-average remediation times. Actual costs may vary based on team familiarity and codebase complexity.\n Rates shown reflect UK market mid-range (£80/hr) and senior (£120/hr) developer costs.\n </div>\n `:'\n <div style="font-size:0.85rem; color:var(--green); padding:1rem; background:rgba(0,255,136,0.05); border-radius:8px; border:1px solid rgba(0,255,136,0.15);">\n No significant remediation items detected. This codebase meets investment-grade quality standards.\n </div>\n '}\n</div>\n`}\n\n\x3c!-- Team Competency Signals --\x3e\n${"full"!==e.tier?"":`\n<div class="section">\n <div class="section-header">\n <span class="icon">👥</span>\n <h3>Team Competency Signals</h3>\n </div>\n <p style="font-size:0.8rem; color:var(--dim); margin-bottom:1rem;">\n Derived from automated code analysis patterns. These signals indicate engineering team capability\n based on observable code quality metrics, not individual performance.\n </p>\n <table class="competency-table">\n <thead>\n <tr><th>Signal</th><th style="text-align:center">Assessment</th></tr>\n </thead>\n <tbody>${z}</tbody>\n </table>\n</div>\n`}\n\n\x3c!-- Comparable Benchmarks --\x3e\n${"full"!==e.tier?"":`\n<div class="section">\n <div class="section-header">\n <span class="icon">📈</span>\n <h3>Comparable Benchmarks</h3>\n </div>\n <p style="font-size:0.8rem; color:var(--dim); margin-bottom:1.25rem;">\n How this codebase compares to typical trust scores at each funding stage.\n The <span style="color:var(--cyan)">cyan marker</span> indicates this codebase's score of <strong>${e.score}/100</strong>.\n </p>\n <div style="background:var(--surface); border:1px solid var(--border); border-radius:12px; padding:1.5rem 2rem;">\n ${P}\n </div>\n</div>\n`}\n\n${r+o>0&&"free"!==e.tier?`\n<div class="page-break"></div>\n\x3c!-- Hallucination Detail --\x3e\n<div class="section">\n <div class="section-header">\n <span class="icon">🔮</span>\n <h3>AI Hallucination Detail</h3>\n </div>\n <p style="font-size:0.85rem; color:var(--dim); margin-bottom:1rem;">\n These API calls reference methods, modules, or endpoints that do not exist in the libraries being used.\n They were likely generated by an AI coding tool and will fail at runtime.\n </p>\n <table>\n <thead>\n <tr><th>Severity</th><th>Location</th><th>API Call</th><th>Impact</th></tr>\n </thead>\n <tbody>${I}</tbody>\n </table>\n</div>\n`:""}\n\n${a>0?`\n\x3c!-- Ghost Code Detail --\x3e\n<div class="section">\n <div class="section-header">\n <span class="icon">👻</span>\n <h3>Ghost Code — Dead Functions</h3>\n </div>\n <p style="font-size:0.85rem; color:var(--dim); margin-bottom:1rem;">\n ${a} function${a>1?"s":""} exist in the codebase but are never called.\n This represents ${i.toLocaleString()} wasted lines of code (${e.ghostResults.wastedPercent||"?"}% of the codebase).\n </p>\n <table>\n <thead>\n <tr><th>Location</th><th>Function</th><th>Size</th><th>References</th></tr>\n </thead>\n <tbody>${A}</tbody>\n </table>\n</div>\n`:""}\n\n\x3c!-- Technical Debt Cost --\x3e\n<div class="section">\n <div class="section-header">\n <span class="icon">📈</span>\n <h3>Technical Debt Cost Analysis</h3>\n </div>\n <div class="cost-box">\n <div class="cost-grid">\n <div class="cost-item cost-manual">\n <div class="cost-value">£${u.toLocaleString()}</div>\n <div class="cost-label">Manual fix cost (${m} dev-hours)</div>\n </div>\n <div class="cost-item cost-thuban">\n <div class="cost-value">${g}h</div>\n <div class="cost-label">Fix time with Thuban auto-fix</div>\n </div>\n <div class="cost-item cost-saving">\n <div class="cost-value">£${h.toLocaleString()}</div>\n <div class="cost-label">Potential saving (${p}%)</div>\n </div>\n </div>\n </div>\n</div>\n\n\x3c!-- Confidentiality Notice --\x3e\n<div class="confidentiality">\n <strong>CONFIDENTIAL</strong><br>\n This report was generated by Thuban Code Health Engine for investment due diligence purposes.\n Distribution should be limited to authorised investment committee members.\n Thuban does not provide investment advice. This report reflects automated code analysis only.\n</div>\n\n\x3c!-- Footer --\x3e\n<div class="report-footer">\n <div>\n <strong>Thuban</strong> — Code Health Engine<br>\n <a href="https://thuban.dev">thuban.dev</a> | A Silverwings product\n </div>\n <div style="text-align:right;">\n Report: ${e.reportId}<br>\n This report was generated automatically.<br>\n For full details, run: <code style="font-family:var(--mono); color:var(--cyan);">npx thuban scan .</code>\n </div>\n</div>\n\n</body>\n</html>`}_esc(e){return String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}save(e,n){const t=n||this.rootPath,s=path.resolve(t),r=path.resolve(this.rootPath);if(!s.startsWith(r+path.sep)&&s!==r)throw new Error(`Output directory must be within the project root: ${r}`);const o=`thuban-investor-report-${this.generatedAt.toISOString().split("T")[0]}.html`,a=path.join(s,o);return fs.writeFileSync(a,e,"utf-8"),a}}module.exports=InvestorReport;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const fs=require("fs"),path=require("path"),{execFileSync:execFileSync}=require("child_process"),EventEmitter=require("events"),ROOT=path.join(__dirname,".."),SERVER=path.join(ROOT,"server"),MANIFEST_PATH=path.join(SERVER,"data","health-check-manifest.json");class MasterHealthChecker extends EventEmitter{constructor(t={}){super(),this.config={rootPath:t.rootPath||ROOT,serverPath:t.serverPath||SERVER,timeout:t.timeout||5e3,...t},this.manifest=this._loadManifest(),this.lastResults=null,this.issueCount=0}_loadManifest(){try{if(fs.existsSync(MANIFEST_PATH))return JSON.parse(fs.readFileSync(MANIFEST_PATH,"utf8"))}catch(t){console.error("[MASTER-HEALTH] Failed to load manifest")}return null}async runFullCheck(){console.log("[MASTER-HEALTH] Starting full system health check (47 checkpoints)...");const t=Date.now(),s={timestamp:(new Date).toISOString(),duration:0,totalChecks:0,passed:0,failed:0,warnings:0,systems:{},criticalIssues:[],autoHealAttempted:[],humanEscalationNeeded:[]},e=[{id:"server",fn:()=>this._checkServer()},{id:"senate",fn:()=>this._checkSenate()},{id:"citadel",fn:()=>this._checkCitadel()},{id:"shadowRealm",fn:()=>this._checkShadowRealm()},{id:"forge",fn:()=>this._checkForge()},{id:"ocee",fn:()=>this._checkOCEE()},{id:"memory",fn:()=>this._checkMemory()},{id:"external",fn:()=>this._checkExternal()}];for(const t of e)try{const e=await t.fn();s.systems[t.id]=e,s.totalChecks+=e.checks.length,s.passed+=e.checks.filter(t=>"PASS"===t.status).length,s.failed+=e.checks.filter(t=>"FAIL"===t.status).length,s.warnings+=e.checks.filter(t=>"WARN"===t.status).length;const i=e.checks.filter(t=>"FAIL"===t.status&&"CRITICAL"===t.criticality);s.criticalIssues.push(...i);const a=e.checks.filter(t=>t.needsHumanEscalation);s.humanEscalationNeeded.push(...a)}catch(e){s.systems[t.id]={status:"ERROR",error:e.message,checks:[]}}return s.duration=Date.now()-t,s.overallStatus=this._calculateOverallStatus(s),this.lastResults=s,this.emit("checkComplete",s),console.log(`[MASTER-HEALTH] Complete: ${s.passed}/${s.totalChecks} passed (${s.duration}ms)`),s}async runQuickCheck(){console.log("[MASTER-HEALTH] Running quick check (critical systems)...");const t={timestamp:(new Date).toISOString(),type:"quick",checks:[]};t.checks.push(await this._check("SRV-001","Server Process",()=>this._fileExists(path.join(this.config.serverPath,"server.js")))),t.checks.push(await this._check("SEN-003","Model Registry",()=>{const t=path.join(this.config.serverPath,"data","model-registry.json");if(!fs.existsSync(t))return!1;const s=JSON.parse(fs.readFileSync(t,"utf8"));return Object.keys(s.providers||{}).length>=3})),t.checks.push(await this._check("CIT-001","Constitution",()=>{const t=path.join(this.config.rootPath,"citadel","constitution.json");return this._fileExists(t)&&this._isValidJson(t)})),t.checks.push(await this._check("CIT-002","File Guard",()=>this._fileExists(path.join(this.config.rootPath,"citadel","file-guard.js"))));const s=t.checks.filter(t=>"PASS"===t.status).length;return console.log(`[MASTER-HEALTH] Quick check: ${s}/${t.checks.length} passed`),t}async _checkServer(){const t=[];return t.push(await this._check("SRV-001","Server Files",()=>this._fileExists(path.join(this.config.serverPath,"server.js"))&&this._fileExists(path.join(this.config.serverPath,"package.json")),"CRITICAL")),t.push(await this._check("SRV-002","Node Modules",()=>this._fileExists(path.join(this.config.serverPath,"node_modules")),"HIGH","npm install")),t.push(await this._check("SRV-003","Package Valid",()=>this._isValidJson(path.join(this.config.serverPath,"package.json")),"HIGH")),t.push(await this._check("SRV-004","Data Directory",()=>this._dirExists(path.join(this.config.serverPath,"data")),"MEDIUM")),t.push(await this._check("SRV-005","Environment",()=>this._fileExists(path.join(this.config.rootPath,".env"))||void 0!==process.env.ANTHROPIC_API_KEY,"HIGH")),{status:this._systemStatus(t),checks:t}}async _checkSenate(){const t=[];return t.push(await this._check("SEN-001","Model Registry",()=>{const t=path.join(this.config.serverPath,"data","model-registry.json");return this._isValidJson(t)},"CRITICAL","Restore from snapshot")),t.push(await this._check("SEN-002","Senate Weights",()=>{const t=path.join(this.config.serverPath,"data","senate-weights-v2.json");return this._isValidJson(t)},"HIGH","Reset to defaults")),t.push(await this._check("SEN-003","Providers Configured",()=>{const t=path.join(this.config.serverPath,"data","model-registry.json");if(!this._isValidJson(t))return!1;const s=JSON.parse(fs.readFileSync(t,"utf8"));return Object.keys(s.providers||{}).length>=5},"CRITICAL")),t.push(await this._check("SEN-004","Senate Core",()=>this._fileExists(path.join(this.config.serverPath,"senate-v2.js"))||this._fileExists(path.join(this.config.serverPath,"senate.js")),"CRITICAL")),t.push(await this._check("SEN-005","Response Cache",()=>{const t=path.join(this.config.serverPath,"data","response-cache.json");return!this._fileExists(t)||this._isValidJson(t)},"LOW")),{status:this._systemStatus(t),checks:t}}async _checkCitadel(){const t=[];return t.push(await this._check("CIT-001","Constitution",()=>{const t=path.join(this.config.rootPath,"citadel","constitution.json");return this._isValidJson(t)},"CRITICAL","HALT - Safety rules missing")),t.push(await this._check("CIT-002","File Guard",()=>this._fileExists(path.join(this.config.rootPath,"citadel","file-guard.js")),"CRITICAL")),t.push(await this._check("CIT-003","Enforcer",()=>this._fileExists(path.join(this.config.rootPath,"citadel","enforcer.js")),"CRITICAL")),t.push(await this._check("CIT-004","Watchers",()=>this._fileExists(path.join(this.config.rootPath,"citadel","watchers.js")),"HIGH")),t.push(await this._check("CIT-005","Audit Directory",()=>this._dirExists(path.join(this.config.rootPath,"citadel","audit")),"MEDIUM","Create directory")),{status:this._systemStatus(t),checks:t}}async _checkShadowRealm(){const t=[];return t.push(await this._check("SHD-001","Shadow Realm V2",()=>this._fileExists(path.join(this.config.rootPath,"build-engine","orion-core","shadow-realm-v2.js")),"CRITICAL")),t.push(await this._check("SHD-002","Node Binary",()=>{try{return execFileSync("node",["--version"],{stdio:"pipe"}),!0}catch{return!1}},"CRITICAL")),t.push(await this._check("SHD-003","Temp Writable",()=>{const t=require("os"),s=path.join(t.tmpdir(),"orion-health-test-"+Date.now());try{return fs.writeFileSync(s,"test"),fs.unlinkSync(s),!0}catch{return!1}},"HIGH")),t.push(await this._check("SHD-004","Healing Loop",()=>this._fileExists(path.join(this.config.rootPath,"build-engine","orion-core","healing-loop.js")),"HIGH")),{status:this._systemStatus(t),checks:t}}async _checkForge(){const t=[],s=path.join(this.config.rootPath,"forge");return t.push(await this._check("FRG-001","Forge Core",()=>this._fileExists(path.join(s,"forge-core.js")),"HIGH")),t.push(await this._check("FRG-002","Task Decomposer",()=>this._fileExists(path.join(s,"task-decomposer.js")),"MEDIUM")),t.push(await this._check("FRG-003","Intent Matcher",()=>this._fileExists(path.join(s,"intent-matcher.js")),"MEDIUM")),t.push(await this._check("FRG-004","Diagnostician",()=>this._fileExists(path.join(s,"diagnostician-v2.js"))||this._fileExists(path.join(s,"diagnostician.js")),"MEDIUM")),t.push(await this._check("FRG-005","Foreman",()=>this._fileExists(path.join(this.config.rootPath,"build-engine","orion-core","foreman.js")),"HIGH")),{status:this._systemStatus(t),checks:t}}async _checkOCEE(){const t=[],s=path.join(this.config.serverPath,"ocee");return t.push(await this._check("OCE-001","OCEE Core",()=>this._fileExists(path.join(s,"ocee-core.js")),"HIGH")),t.push(await this._check("OCE-002","Task Queue",()=>this._fileExists(path.join(s,"persistent-task-queue.js")),"HIGH")),t.push(await this._check("OCE-003","Checkpoint Manager",()=>this._fileExists(path.join(s,"checkpoint-manager.js")),"HIGH")),t.push(await this._check("OCE-004","Build Sessions",()=>{const t=path.join(this.config.serverPath,"data","build-sessions.json");return!this._fileExists(t)||this._isValidJson(t)},"MEDIUM")),t.push(await this._check("OCE-005","Executor Status",()=>{const t=path.join(this.config.serverPath,"data","executor-status.json");return this._isValidJson(t)},"MEDIUM")),{status:this._systemStatus(t),checks:t}}async _checkMemory(){const t=[];return t.push(await this._check("MEM-001","Orion Knowledge",()=>this._isValidJson(path.join(this.config.rootPath,"orion-knowledge.json")),"MEDIUM","Reinitialize")),t.push(await this._check("MEM-002","Memory Bank",()=>{const t=path.join(this.config.rootPath,"memory-bank");return this._fileExists(path.join(t,"progress.md"))&&this._fileExists(path.join(t,"activeContext.md"))},"MEDIUM")),t.push(await this._check("MEM-003","Snapshot Manifest",()=>{const t=path.join(this.config.serverPath,".orion","snapshot-manifest.json");return!this._fileExists(t)||this._isValidJson(t)},"MEDIUM")),t.push(await this._check("MEM-004","Build Logs",()=>this._dirExists(path.join(this.config.serverPath,"data","build-logs")),"MEDIUM")),t.push(await this._check("MEM-005","Failure Memory",()=>this._fileExists(path.join(this.config.serverPath,"services","failure-memory.js")),"MEDIUM")),{status:this._systemStatus(t),checks:t}}async _checkExternal(){const t=[];return t.push(await this._check("EXT-001","Zoho Tokens",()=>{const t=path.join(this.config.serverPath,"data","zoho-tokens.json");return!this._fileExists(t)||this._isValidJson(t)},"LOW")),t.push(await this._check("EXT-002","Cartography",()=>this._dirExists(path.join(this.config.rootPath,"cartography")),"LOW")),t.push(await this._check("EXT-003","Notification Config",()=>{const t=path.join(this.config.serverPath,"data","notification-config.json");return!this._fileExists(t)||this._isValidJson(t)},"LOW")),t.push(await this._check("EXT-004","Health History",()=>{const t=path.join(this.config.serverPath,"data","health-history.json");return!this._fileExists(t)||this._isValidJson(t)},"LOW")),{status:this._systemStatus(t),checks:t}}async _check(t,s,e,i="MEDIUM",a=null){const h={id:t,name:s,criticality:i,status:"UNKNOWN",autoHeal:a,needsHumanEscalation:!1};try{const t=await e();h.status=t?"PASS":"FAIL",t||"CRITICAL"!==i||(h.needsHumanEscalation=!0)}catch(t){h.status="ERROR",h.error=t.message,h.needsHumanEscalation=!0}return h}_fileExists(t){try{return fs.existsSync(t)}catch{return!1}}_dirExists(t){try{return fs.existsSync(t)&&fs.statSync(t).isDirectory()}catch{return!1}}_isValidJson(t){try{return!!fs.existsSync(t)&&(JSON.parse(fs.readFileSync(t,"utf8")),!0)}catch{return!1}}_systemStatus(t){const s=t.filter(t=>"FAIL"===t.status||"ERROR"===t.status);return s.filter(t=>"CRITICAL"===t.criticality).length>0?"CRITICAL":s.length>0?"DEGRADED":"HEALTHY"}_calculateOverallStatus(t){return t.criticalIssues.length>0?"CRITICAL":t.failed>0?"DEGRADED":t.warnings>0?"WARNING":"HEALTHY"}getSummary(){return this.lastResults?{status:this.lastResults.overallStatus,passed:this.lastResults.passed,failed:this.lastResults.failed,total:this.lastResults.totalChecks,criticalIssues:this.lastResults.criticalIssues.length,humanActionNeeded:this.lastResults.humanEscalationNeeded.length,lastCheck:this.lastResults.timestamp}:{status:"NO_DATA",message:"No health check run yet"}}}module.exports=MasterHealthChecker;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const fs=require("fs"),path=require("path"),os=require("os"),crypto=require("crypto"),THUBAN_DIR=path.join(os.homedir(),".thuban"),MONITOR_DIR=path.join(THUBAN_DIR,"monitor"),CONFIG_FILE=path.join(MONITOR_DIR,"config.json"),RUNS_DIR=path.join(MONITOR_DIR,"runs"),NOTIFICATIONS_FILE=path.join(MONITOR_DIR,"notifications.json");function ensureDir(t){fs.existsSync(t)||fs.mkdirSync(t,{recursive:!0})}function safeReadJson(t,e){try{return JSON.parse(fs.readFileSync(t,"utf-8"))}catch(t){return e}}function atomicWriteSync(t,e){const n=t+".tmp."+process.pid+"."+Date.now();try{fs.writeFileSync(n,e,"utf-8"),fs.renameSync(n,t)}catch(t){try{fs.unlinkSync(n)}catch{}throw t}}class MonitorStore{constructor(){ensureDir(THUBAN_DIR),ensureDir(MONITOR_DIR),ensureDir(RUNS_DIR)}getRepoId(t){return crypto.createHash("sha256").update(path.resolve(t)).digest("hex").substring(0,12)}loadConfig(){return safeReadJson(CONFIG_FILE,{version:1,repos:[]})}saveConfig(t){atomicWriteSync(CONFIG_FILE,JSON.stringify(t,null,2))}upsertRepo(t){const e=this.loadConfig(),n=t.repoId||this.getRepoId(t.repoPath),o={repoId:n,repoPath:path.resolve(t.repoPath),frequency:t.frequency||"daily",intervalMs:t.intervalMs,notification:t.notification||{channels:["inbox"]},createdAt:t.createdAt||(new Date).toISOString(),updatedAt:(new Date).toISOString(),enabled:!1!==t.enabled,lastRunAt:t.lastRunAt||null,nextRunAt:t.nextRunAt||null},r=e.repos.findIndex(t=>t.repoId===n);return r>=0?e.repos[r]={...e.repos[r],...o}:e.repos.push(o),this.saveConfig(e),o}listRepos(){return this.loadConfig().repos||[]}getRepo(t){const e=t?path.resolve(t):null;return this.listRepos().find(n=>n.repoId===t||n.repoPath===e)||null}getRepoRunDir(t){const e=path.join(RUNS_DIR,t);return ensureDir(e),e}saveRun(t,e){const n=this.getRepoRunDir(t),o=path.join(n,`${e.timestamp.replace(/[:.]/g,"-")}.json`);return atomicWriteSync(o,JSON.stringify(e,null,2)),o}listRuns(t){const e=this.getRepoRunDir(t);return fs.readdirSync(e).filter(t=>t.endsWith(".json")).sort().map(t=>safeReadJson(path.join(e,t),null)).filter(Boolean)}getLatestRun(t){const e=this.listRuns(t);return e.length?e[e.length-1]:null}appendNotification(t){const e=safeReadJson(NOTIFICATIONS_FILE,{notifications:[]});e.notifications.push(t),atomicWriteSync(NOTIFICATIONS_FILE,JSON.stringify(e,null,2))}getNotifications(t=20){return safeReadJson(NOTIFICATIONS_FILE,{notifications:[]}).notifications.slice(-t).reverse()}}module.exports=MonitorStore;
|
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Thuban Python AST Helper
|
|
4
|
-
|
|
5
|
-
Reads Python source from stdin, parses it with the built-in `ast` module,
|
|
6
|
-
and prints a single-line JSON report to stdout describing:
|
|
7
|
-
|
|
8
|
-
- unused_import Imported names never referenced anywhere in the file
|
|
9
|
-
- unused_variable Local variables assigned in a function but never read
|
|
10
|
-
- high_complexity Functions whose McCabe cyclomatic complexity exceeds
|
|
11
|
-
COMPLEXITY_THRESHOLD
|
|
12
|
-
- dead_code Statements that are unreachable because they follow
|
|
13
|
-
an unconditional return/raise/break/continue in the
|
|
14
|
-
same block
|
|
15
|
-
- bare_except `except:` clauses with no exception type
|
|
16
|
-
- mutable_default_arg Function parameters defaulting to a mutable literal
|
|
17
|
-
(list/dict/set) or list()/dict()/set() call
|
|
18
|
-
|
|
19
|
-
This script is invoked by packages/scanner/python-ast-analyzer.js as a
|
|
20
|
-
subprocess (one call per Python file). It must never raise past main() -
|
|
21
|
-
on any parse failure it prints {"ok": false, "error": "..."} and exits 0,
|
|
22
|
-
so the caller can treat AST analysis as a best-effort supplement.
|
|
23
|
-
|
|
24
|
-
Output contract (stdout, single JSON object):
|
|
25
|
-
{"ok": true, "issues": [{"type": str, "line": int, "name": str|null, "message": str}, ...]}
|
|
26
|
-
{"ok": false, "error": str}
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
import ast
|
|
30
|
-
import json
|
|
31
|
-
import sys
|
|
32
|
-
|
|
33
|
-
COMPLEXITY_THRESHOLD = 10
|
|
34
|
-
|
|
35
|
-
TERMINATOR_TYPES = (ast.Return, ast.Raise, ast.Continue, ast.Break)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
39
|
-
# Unused imports
|
|
40
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
41
|
-
|
|
42
|
-
class _UnusedImportChecker:
|
|
43
|
-
def __init__(self, tree):
|
|
44
|
-
self.tree = tree
|
|
45
|
-
self.imports = [] # [{'name', 'line', 'source'}]
|
|
46
|
-
self.used_names = set()
|
|
47
|
-
self.dunder_all_names = set()
|
|
48
|
-
|
|
49
|
-
def collect(self):
|
|
50
|
-
for node in ast.walk(self.tree):
|
|
51
|
-
if isinstance(node, ast.Import):
|
|
52
|
-
for alias in node.names:
|
|
53
|
-
if alias.name == '*':
|
|
54
|
-
continue
|
|
55
|
-
bound = alias.asname or alias.name.split('.')[0]
|
|
56
|
-
self.imports.append({'name': bound, 'line': node.lineno, 'source': ''})
|
|
57
|
-
elif isinstance(node, ast.ImportFrom):
|
|
58
|
-
if node.module == '__future__':
|
|
59
|
-
continue
|
|
60
|
-
for alias in node.names:
|
|
61
|
-
if alias.name == '*':
|
|
62
|
-
continue
|
|
63
|
-
bound = alias.asname or alias.name
|
|
64
|
-
self.imports.append({'name': bound, 'line': node.lineno, 'source': node.module or ''})
|
|
65
|
-
elif isinstance(node, ast.Name) and isinstance(node.ctx, ast.Load):
|
|
66
|
-
self.used_names.add(node.id)
|
|
67
|
-
elif isinstance(node, ast.Assign):
|
|
68
|
-
for target in node.targets:
|
|
69
|
-
if isinstance(target, ast.Name) and target.id == '__all__' and \
|
|
70
|
-
isinstance(node.value, (ast.List, ast.Tuple, ast.Set)):
|
|
71
|
-
for elt in node.value.elts:
|
|
72
|
-
if isinstance(elt, ast.Constant) and isinstance(elt.value, str):
|
|
73
|
-
self.dunder_all_names.add(elt.value)
|
|
74
|
-
|
|
75
|
-
def unused(self):
|
|
76
|
-
issues = []
|
|
77
|
-
seen = set()
|
|
78
|
-
for imp in self.imports:
|
|
79
|
-
name = imp['name']
|
|
80
|
-
if name.startswith('_'):
|
|
81
|
-
continue
|
|
82
|
-
if name in self.used_names or name in self.dunder_all_names:
|
|
83
|
-
continue
|
|
84
|
-
key = (name, imp['line'])
|
|
85
|
-
if key in seen:
|
|
86
|
-
continue
|
|
87
|
-
seen.add(key)
|
|
88
|
-
source_suffix = " from '%s'" % imp['source'] if imp['source'] else ''
|
|
89
|
-
issues.append({
|
|
90
|
-
'type': 'unused_import',
|
|
91
|
-
'line': imp['line'],
|
|
92
|
-
'name': name,
|
|
93
|
-
'message': "Unused import: '%s'%s" % (name, source_suffix),
|
|
94
|
-
})
|
|
95
|
-
return issues
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
99
|
-
# Per-function analysis: complexity, unused locals, mutable defaults
|
|
100
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
101
|
-
|
|
102
|
-
class _ComplexityVisitor(ast.NodeVisitor):
|
|
103
|
-
"""Counts McCabe decision points within a single function's own body,
|
|
104
|
-
stopping at nested function/lambda boundaries (those are analyzed
|
|
105
|
-
independently when ast.walk() reaches them on its own)."""
|
|
106
|
-
|
|
107
|
-
def __init__(self):
|
|
108
|
-
self.complexity = 1
|
|
109
|
-
|
|
110
|
-
def visit_If(self, node):
|
|
111
|
-
self.complexity += 1
|
|
112
|
-
self.generic_visit(node)
|
|
113
|
-
|
|
114
|
-
def visit_For(self, node):
|
|
115
|
-
self.complexity += 1
|
|
116
|
-
self.generic_visit(node)
|
|
117
|
-
|
|
118
|
-
def visit_AsyncFor(self, node):
|
|
119
|
-
self.complexity += 1
|
|
120
|
-
self.generic_visit(node)
|
|
121
|
-
|
|
122
|
-
def visit_While(self, node):
|
|
123
|
-
self.complexity += 1
|
|
124
|
-
self.generic_visit(node)
|
|
125
|
-
|
|
126
|
-
def visit_IfExp(self, node):
|
|
127
|
-
self.complexity += 1
|
|
128
|
-
self.generic_visit(node)
|
|
129
|
-
|
|
130
|
-
def visit_ExceptHandler(self, node):
|
|
131
|
-
self.complexity += 1
|
|
132
|
-
self.generic_visit(node)
|
|
133
|
-
|
|
134
|
-
def visit_BoolOp(self, node):
|
|
135
|
-
self.complexity += max(len(node.values) - 1, 0)
|
|
136
|
-
self.generic_visit(node)
|
|
137
|
-
|
|
138
|
-
def visit_comprehension(self, node):
|
|
139
|
-
self.complexity += len(node.ifs)
|
|
140
|
-
self.generic_visit(node)
|
|
141
|
-
|
|
142
|
-
# Nested scopes get their own complexity computation - don't descend.
|
|
143
|
-
def visit_FunctionDef(self, node):
|
|
144
|
-
pass
|
|
145
|
-
|
|
146
|
-
def visit_AsyncFunctionDef(self, node):
|
|
147
|
-
pass
|
|
148
|
-
|
|
149
|
-
def visit_Lambda(self, node):
|
|
150
|
-
pass
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
def _compute_complexity(fn):
|
|
154
|
-
visitor = _ComplexityVisitor()
|
|
155
|
-
for stmt in fn.body:
|
|
156
|
-
visitor.visit(stmt)
|
|
157
|
-
return visitor.complexity
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
def _is_mutable_default(default):
|
|
161
|
-
if isinstance(default, (ast.List, ast.Dict, ast.Set)):
|
|
162
|
-
return True
|
|
163
|
-
if isinstance(default, ast.Call) and isinstance(default.func, ast.Name):
|
|
164
|
-
return default.func.id in ('list', 'dict', 'set')
|
|
165
|
-
return False
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
def _mutable_defaults(fn):
|
|
169
|
-
issues = []
|
|
170
|
-
args = fn.args
|
|
171
|
-
positional = list(getattr(args, 'posonlyargs', [])) + list(args.args)
|
|
172
|
-
if args.defaults:
|
|
173
|
-
for arg, default in zip(reversed(positional), reversed(args.defaults)):
|
|
174
|
-
if _is_mutable_default(default):
|
|
175
|
-
issues.append({
|
|
176
|
-
'type': 'mutable_default_arg',
|
|
177
|
-
'line': default.lineno,
|
|
178
|
-
'name': arg.arg,
|
|
179
|
-
'message': "Mutable default argument '%s' in function '%s' - shared across all calls" % (arg.arg, fn.name),
|
|
180
|
-
})
|
|
181
|
-
for arg, default in zip(args.kwonlyargs, args.kw_defaults or []):
|
|
182
|
-
if default is not None and _is_mutable_default(default):
|
|
183
|
-
issues.append({
|
|
184
|
-
'type': 'mutable_default_arg',
|
|
185
|
-
'line': default.lineno,
|
|
186
|
-
'name': arg.arg,
|
|
187
|
-
'message': "Mutable default argument '%s' in function '%s' - shared across all calls" % (arg.arg, fn.name),
|
|
188
|
-
})
|
|
189
|
-
return issues
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
class _LocalAssignCollector(ast.NodeVisitor):
|
|
193
|
-
"""Collects simple (single-Name-target) local assignments made directly
|
|
194
|
-
within a function's own body - not inside nested function/lambda
|
|
195
|
-
scopes, which own their own locals."""
|
|
196
|
-
|
|
197
|
-
def __init__(self):
|
|
198
|
-
self.assigned = {} # name -> first assignment line
|
|
199
|
-
self.declared_global_nonlocal = set()
|
|
200
|
-
|
|
201
|
-
def visit_Assign(self, node):
|
|
202
|
-
if len(node.targets) == 1 and isinstance(node.targets[0], ast.Name):
|
|
203
|
-
name = node.targets[0].id
|
|
204
|
-
self.assigned.setdefault(name, node.lineno)
|
|
205
|
-
self.generic_visit(node)
|
|
206
|
-
|
|
207
|
-
def visit_AnnAssign(self, node):
|
|
208
|
-
if isinstance(node.target, ast.Name) and node.value is not None:
|
|
209
|
-
self.assigned.setdefault(node.target.id, node.lineno)
|
|
210
|
-
self.generic_visit(node)
|
|
211
|
-
|
|
212
|
-
def visit_For(self, node):
|
|
213
|
-
if isinstance(node.target, ast.Name):
|
|
214
|
-
self.assigned.setdefault(node.target.id, node.lineno)
|
|
215
|
-
self.generic_visit(node)
|
|
216
|
-
|
|
217
|
-
def visit_With(self, node):
|
|
218
|
-
for item in node.items:
|
|
219
|
-
if item.optional_vars is not None and isinstance(item.optional_vars, ast.Name):
|
|
220
|
-
self.assigned.setdefault(item.optional_vars.id, node.lineno)
|
|
221
|
-
self.generic_visit(node)
|
|
222
|
-
|
|
223
|
-
def visit_Global(self, node):
|
|
224
|
-
self.declared_global_nonlocal.update(node.names)
|
|
225
|
-
|
|
226
|
-
def visit_Nonlocal(self, node):
|
|
227
|
-
self.declared_global_nonlocal.update(node.names)
|
|
228
|
-
|
|
229
|
-
def visit_FunctionDef(self, node):
|
|
230
|
-
pass
|
|
231
|
-
|
|
232
|
-
def visit_AsyncFunctionDef(self, node):
|
|
233
|
-
pass
|
|
234
|
-
|
|
235
|
-
def visit_Lambda(self, node):
|
|
236
|
-
pass
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
class _LoadNameCollector(ast.NodeVisitor):
|
|
240
|
-
"""Collects every Name read (Load context) anywhere within a subtree,
|
|
241
|
-
INCLUDING nested functions/lambdas - a variable captured by a closure
|
|
242
|
-
still counts as used."""
|
|
243
|
-
|
|
244
|
-
def __init__(self):
|
|
245
|
-
self.loaded = set()
|
|
246
|
-
|
|
247
|
-
def visit_Name(self, node):
|
|
248
|
-
if isinstance(node.ctx, ast.Load):
|
|
249
|
-
self.loaded.add(node.id)
|
|
250
|
-
self.generic_visit(node)
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
def _unused_locals(fn):
|
|
254
|
-
assign_collector = _LocalAssignCollector()
|
|
255
|
-
for stmt in fn.body:
|
|
256
|
-
assign_collector.visit(stmt)
|
|
257
|
-
|
|
258
|
-
load_collector = _LoadNameCollector()
|
|
259
|
-
load_collector.visit(fn)
|
|
260
|
-
|
|
261
|
-
issues = []
|
|
262
|
-
for name, line in assign_collector.assigned.items():
|
|
263
|
-
if name.startswith('_'):
|
|
264
|
-
continue
|
|
265
|
-
if name in assign_collector.declared_global_nonlocal:
|
|
266
|
-
continue
|
|
267
|
-
if name in load_collector.loaded:
|
|
268
|
-
continue
|
|
269
|
-
issues.append({
|
|
270
|
-
'type': 'unused_variable',
|
|
271
|
-
'line': line,
|
|
272
|
-
'name': name,
|
|
273
|
-
'message': "Variable '%s' is assigned but never used" % name,
|
|
274
|
-
})
|
|
275
|
-
return issues
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
279
|
-
# Dead code (unreachable statements)
|
|
280
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
281
|
-
|
|
282
|
-
def _check_block(stmts, issues):
|
|
283
|
-
for i, stmt in enumerate(stmts):
|
|
284
|
-
if isinstance(stmt, TERMINATOR_TYPES):
|
|
285
|
-
if i + 1 < len(stmts):
|
|
286
|
-
nxt = stmts[i + 1]
|
|
287
|
-
kind = type(stmt).__name__.lower()
|
|
288
|
-
issues.append({
|
|
289
|
-
'type': 'dead_code',
|
|
290
|
-
'line': nxt.lineno,
|
|
291
|
-
'name': None,
|
|
292
|
-
'message': "Unreachable code after '%s' statement" % kind,
|
|
293
|
-
})
|
|
294
|
-
break # only report the first unreachable run per block
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
class _DeadCodeVisitor(ast.NodeVisitor):
|
|
298
|
-
def __init__(self):
|
|
299
|
-
self.issues = []
|
|
300
|
-
|
|
301
|
-
def visit_Module(self, node):
|
|
302
|
-
_check_block(node.body, self.issues)
|
|
303
|
-
self.generic_visit(node)
|
|
304
|
-
|
|
305
|
-
def visit_FunctionDef(self, node):
|
|
306
|
-
_check_block(node.body, self.issues)
|
|
307
|
-
self.generic_visit(node)
|
|
308
|
-
|
|
309
|
-
def visit_AsyncFunctionDef(self, node):
|
|
310
|
-
_check_block(node.body, self.issues)
|
|
311
|
-
self.generic_visit(node)
|
|
312
|
-
|
|
313
|
-
def visit_If(self, node):
|
|
314
|
-
_check_block(node.body, self.issues)
|
|
315
|
-
_check_block(node.orelse, self.issues)
|
|
316
|
-
self.generic_visit(node)
|
|
317
|
-
|
|
318
|
-
def visit_For(self, node):
|
|
319
|
-
_check_block(node.body, self.issues)
|
|
320
|
-
_check_block(node.orelse, self.issues)
|
|
321
|
-
self.generic_visit(node)
|
|
322
|
-
|
|
323
|
-
def visit_AsyncFor(self, node):
|
|
324
|
-
_check_block(node.body, self.issues)
|
|
325
|
-
_check_block(node.orelse, self.issues)
|
|
326
|
-
self.generic_visit(node)
|
|
327
|
-
|
|
328
|
-
def visit_While(self, node):
|
|
329
|
-
_check_block(node.body, self.issues)
|
|
330
|
-
_check_block(node.orelse, self.issues)
|
|
331
|
-
self.generic_visit(node)
|
|
332
|
-
|
|
333
|
-
def visit_Try(self, node):
|
|
334
|
-
_check_block(node.body, self.issues)
|
|
335
|
-
for handler in node.handlers:
|
|
336
|
-
_check_block(handler.body, self.issues)
|
|
337
|
-
_check_block(node.orelse, self.issues)
|
|
338
|
-
_check_block(node.finalbody, self.issues)
|
|
339
|
-
self.generic_visit(node)
|
|
340
|
-
|
|
341
|
-
def visit_With(self, node):
|
|
342
|
-
_check_block(node.body, self.issues)
|
|
343
|
-
self.generic_visit(node)
|
|
344
|
-
|
|
345
|
-
def visit_AsyncWith(self, node):
|
|
346
|
-
_check_block(node.body, self.issues)
|
|
347
|
-
self.generic_visit(node)
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
351
|
-
# Suspicious patterns: bare except
|
|
352
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
353
|
-
|
|
354
|
-
def _find_bare_except(tree):
|
|
355
|
-
issues = []
|
|
356
|
-
for node in ast.walk(tree):
|
|
357
|
-
if isinstance(node, ast.ExceptHandler) and node.type is None:
|
|
358
|
-
issues.append({
|
|
359
|
-
'type': 'bare_except',
|
|
360
|
-
'line': node.lineno,
|
|
361
|
-
'name': None,
|
|
362
|
-
'message': "Bare 'except:' catches all exceptions including SystemExit/KeyboardInterrupt - catch specific exception types instead",
|
|
363
|
-
})
|
|
364
|
-
return issues
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
368
|
-
# Entry point
|
|
369
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
370
|
-
|
|
371
|
-
def main():
|
|
372
|
-
source = sys.stdin.read()
|
|
373
|
-
|
|
374
|
-
try:
|
|
375
|
-
tree = ast.parse(source)
|
|
376
|
-
except SyntaxError as e:
|
|
377
|
-
print(json.dumps({'ok': False, 'error': 'SyntaxError: %s' % e}))
|
|
378
|
-
return
|
|
379
|
-
except Exception as e: # pragma: no cover - defensive
|
|
380
|
-
print(json.dumps({'ok': False, 'error': str(e)}))
|
|
381
|
-
return
|
|
382
|
-
|
|
383
|
-
issues = []
|
|
384
|
-
|
|
385
|
-
try:
|
|
386
|
-
importer = _UnusedImportChecker(tree)
|
|
387
|
-
importer.collect()
|
|
388
|
-
issues.extend(importer.unused())
|
|
389
|
-
except Exception:
|
|
390
|
-
pass
|
|
391
|
-
|
|
392
|
-
try:
|
|
393
|
-
for node in ast.walk(tree):
|
|
394
|
-
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
395
|
-
issues.extend(_mutable_defaults(node))
|
|
396
|
-
complexity = _compute_complexity(node)
|
|
397
|
-
if complexity > COMPLEXITY_THRESHOLD:
|
|
398
|
-
issues.append({
|
|
399
|
-
'type': 'high_complexity',
|
|
400
|
-
'line': node.lineno,
|
|
401
|
-
'name': node.name,
|
|
402
|
-
'message': "Function '%s' has cyclomatic complexity %d (threshold %d)" % (
|
|
403
|
-
node.name, complexity, COMPLEXITY_THRESHOLD),
|
|
404
|
-
})
|
|
405
|
-
issues.extend(_unused_locals(node))
|
|
406
|
-
except Exception:
|
|
407
|
-
pass
|
|
408
|
-
|
|
409
|
-
try:
|
|
410
|
-
dead_code_visitor = _DeadCodeVisitor()
|
|
411
|
-
dead_code_visitor.visit(tree)
|
|
412
|
-
issues.extend(dead_code_visitor.issues)
|
|
413
|
-
except Exception:
|
|
414
|
-
pass
|
|
415
|
-
|
|
416
|
-
try:
|
|
417
|
-
issues.extend(_find_bare_except(tree))
|
|
418
|
-
except Exception:
|
|
419
|
-
pass
|
|
420
|
-
|
|
421
|
-
issues.sort(key=lambda i: i.get('line') or 0)
|
|
422
|
-
print(json.dumps({'ok': True, 'issues': issues}))
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
if __name__ == '__main__':
|
|
426
|
-
main()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const fs=require("fs"),path=require("path"),crypto=require("crypto"),EventEmitter=require("events"),{execFileSync:execFileSync}=require("child_process");class SecretScanner extends EventEmitter{constructor(e={}){super();const t=new Set(["rootPath","ignorePatterns","maxFileSize","entropyThreshold","minEntropyLength","includeGitHistory"]),i={};for(const s of Object.keys(e))t.has(s)&&(i[s]=e[s]);this.config={rootPath:i.rootPath||process.cwd(),ignorePatterns:i.ignorePatterns||["node_modules/**",".git/**","dist/**",".next/**","coverage/**"],maxFileSize:i.maxFileSize||1048576,entropyThreshold:i.entropyThreshold||4.2,minEntropyLength:i.minEntropyLength||20,includeGitHistory:void 0===i.includeGitHistory||i.includeGitHistory},this.scanExtensions=new Set([".env",".js",".jsx",".ts",".tsx",".py",".json",".yaml",".yml",".toml",".ini",".conf",".config",".properties",".sh",".bash",".zsh"]),this.ignoredDirectories=["node_modules",".git","dist",".next","coverage",".venv","venv","__pycache__"],this.safeLinePatterns=[/process\.env\./i,/process\.env\[/i,/os\.environ/i,/sample/i,/placeholder/i,/dummy/i,/mock/i,/example/i,/replace[_-\s]?me/i,/replace[_-\s]?with/i,/local-dev-token/i,/changeme/i,/your[_-\s]?key/i,/your[_-\s]?(secret|token|password)/i,/<secret>/i,/<token>/i,/x{8,}/i],this.secretPatterns=[{id:"SECRET001",type:"Stripe Secret Key",severity:"critical",recommendation:"Move this key to a cloud secret manager and load it via environment variables.",pattern:/\bsk_(live|test)_[0-9a-zA-Z]{16,}\b/gi},{id:"SECRET002",type:"Stripe Publishable Key",severity:"high",recommendation:"Verify this publishable key is intended to be public; if not, move it to managed secrets.",pattern:/\bpk_(live|test)_[0-9a-zA-Z]{16,}\b/gi},{id:"SECRET003",type:"AWS Access Key",severity:"critical",recommendation:"Rotate the AWS credential immediately and store replacements in a cloud secret manager.",pattern:/\b(AKIA|ASIA|AGPA|AIDA|AROA|AIPA)[A-Z0-9]{16}\b/g},{id:"SECRET004",type:"GitHub Token",severity:"critical",recommendation:"Revoke the GitHub token and replace it with a managed secret or GitHub App credential.",pattern:/\b(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\b/g},{id:"SECRET005",type:"Slack Token",severity:"critical",recommendation:"Rotate the Slack token and move it into a cloud secret manager.",pattern:/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g},{id:"SECRET006",type:"Twilio Credential",severity:"critical",recommendation:"Rotate the Twilio credential and store it in managed secrets.",pattern:/\b(SK|AC)[0-9a-fA-F]{32}\b/g},{id:"SECRET007",type:"Google API Key",severity:"critical",recommendation:"Restrict and rotate the Google API key, then move it to a cloud secret manager.",pattern:/\bAIza[0-9A-Za-z\-_]{35}\b/g},{id:"SECRET007B",type:"OpenAI Project Key",severity:"critical",recommendation:"Rotate the OpenAI project key and move it to a cloud secret manager.",pattern:/\bsk-proj-[A-Za-z0-9\-_]{20,}\b/g},{id:"SECRET007C",type:"Cartesia API Key",severity:"critical",recommendation:"Rotate the Cartesia API key and move it to a cloud secret manager.",pattern:/\bsk_car_[A-Za-z0-9]{16,}\b/g},{id:"SECRET008",type:"JWT Token",severity:"high",recommendation:"Do not hardcode JWTs; issue them dynamically and store signing secrets in managed secrets.",pattern:/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9._-]{8,}\.[A-Za-z0-9._-]{8,}\b/g},{id:"SECRET009",type:"Bearer Token",severity:"high",recommendation:"Move bearer tokens to a cloud secret manager and inject them at runtime.",pattern:/\bBearer\s+[A-Za-z0-9\-._~+/]+=*\b/g},{id:"SECRET010",type:"Private Key",severity:"critical",recommendation:"Remove the private key from source control, rotate it, and store it in a secret manager.",pattern:/-----BEGIN (RSA |DSA |EC |OPENSSH |PGP )?PRIVATE KEY-----/g},{id:"SECRET011",type:"Database Connection String with Password",severity:"critical",recommendation:"Move the connection string to managed secrets and avoid embedding passwords in code or config.",pattern:/\b(?:postgres(?:ql)?|mysql|mssql|mongodb(?:\+srv)?|redis):\/\/[^:\s]+:[^@\s]+@[^'"`\s]+\b/gi},{id:"SECRET012",type:"Webhook Secret",severity:"high",recommendation:"Store webhook secrets in a cloud secret manager and inject them via environment variables.",pattern:/\b(?:whsec_[A-Za-z0-9]+|webhook[_-]?secret[_:=\s'"]+[A-Za-z0-9_\-]{12,})\b/gi},{id:"SECRET013",type:"Hardcoded Password or Secret Assignment",severity:"high",recommendation:"Replace hardcoded credentials with environment variables backed by a cloud secret manager.",pattern:/\b(?:password|passwd|pwd|secret|client_secret|api[_-]?secret|signing[_-]?secret)\b\s*[:=]\s*['"`][^'"`\s][^'"`]{5,}['"`]/gi},{id:"SECRET014",type:"Hardcoded API Key Assignment",severity:"high",recommendation:"Move API keys to a cloud secret manager and reference them through environment variables.",pattern:/\b(?:api[_-]?key|access[_-]?token|auth[_-]?token|token)\b\s*[:=]\s*['"`][A-Za-z0-9_\-./+=]{12,}['"`]/gi},{id:"SECRET015",type:".env File Present",severity:"medium",recommendation:"Ensure .env files are excluded from git and move production secrets to a cloud secret manager.",filePattern:/(^|[\\/])\.env(\.[^\\/]+)?$/i},{id:"SECRET016",type:"LiveKit API Secret",severity:"critical",recommendation:"Rotate the LiveKit API secret and store it in managed secrets.",pattern:/\b(?:LIVEKIT_API_SECRET|livekit[_-]?api[_-]?secret)\b\s*[:=]\s*['"`]?([A-Za-z0-9]{24,})['"`]?/gi}]}async scanAll(){const e=Date.now(),t=await this._discoverFiles(this.config.rootPath),i=[];for(const e of t)i.push(...await this.scanFile(e));return this.config.includeGitHistory&&i.push(...this.scanGitHistory()),{filesScanned:t.length,issues:i,summary:this._summarizeIssues(i),duration:Date.now()-e}}async scanFiles(e){const t=[];for(const i of e)t.push(...await this.scanFile(i));return this.config.includeGitHistory&&t.push(...this.scanGitHistory()),{filesScanned:e.length,issues:t,summary:this._summarizeIssues(t)}}async scanFile(e){const t=[],i=path.relative(this.config.rootPath,e).replace(/\\/g,"/");try{if(fs.statSync(e).size>this.config.maxFileSize)return t;const s=path.basename(e),n=fs.readFileSync(e,"utf8").split(/\r?\n/);for(const r of this.secretPatterns)if(r.filePattern&&r.filePattern.test(e)){if(this._shouldSkipLine(s,i,r))continue;this._isGitIgnored(i)||t.push(this._createIssue({file:e,line:1,type:r.type,severity:r.severity,recommendation:"Add this file to .gitignore and move any production secrets to a cloud secret manager.",id:r.id,match:s,category:"secret"}))}else if(r.pattern)for(let s=0;s<n.length;s++){const o=n[s];if(this._shouldSkipLine(o,i,r))continue;let a;for(r.pattern.lastIndex=0;null!==(a=r.pattern.exec(o));){const i=a[1]||a[0];this._isLikelyPlaceholder(i)||t.push(this._createIssue({file:e,line:s+1,column:a.index,type:r.type,severity:r.severity,recommendation:r.recommendation,id:r.id,match:a[0],category:"secret"}))}}return t.push(...this._scanEntropy(e,n,i)),this._dedupeIssues(t)}catch(t){return[{file:e,line:1,category:"secret",severity:"medium",id:"SECRET_SCAN_ERROR",type:"Secret Scan Error",recommendation:"Verify file permissions and encoding, then rerun the scan.",message:"Failed to scan file for secrets: "+("ENOENT"===t.code?"File not found":"EACCES"===t.code?"Permission denied":"Scan error")}]}}scanGitHistory(){try{const e=execFileSync("git",["log","-p","--all","--full-history","--","."],{cwd:this.config.rootPath,encoding:"utf8",maxBuffer:20971520}),t=[],i=e.split(/\r?\n/);let s=null,n=null;for(const e of i){if(e.startsWith("commit ")){s=e.replace("commit ","").trim();continue}if(e.startsWith("+++ b/")){n=e.replace("+++ b/","").trim();continue}if(!e.startsWith("+")||e.startsWith("+++"))continue;const i=e.slice(1);if(!this._shouldSkipLine(i,n||""))for(const e of this.secretPatterns){if(!e.pattern)continue;let r;for(e.pattern.lastIndex=0;null!==(r=e.pattern.exec(i));){const o=r[1]||r[0];this._isLikelyPlaceholder(o)||t.push({file:n||"unknown",line:null,category:"secret-history",severity:"medium"===e.severity?"high":e.severity,id:`${e.id}_HISTORY`,type:`${e.type} in Git History`,recommendation:"Purge the secret from git history, rotate it, and move it to a cloud secret manager.",message:`Potential secret remains in git history (${s||"unknown commit"})`,commit:s,code:i.trim().slice(0,140)})}}}return this._dedupeIssues(t)}catch(e){return[]}}_scanEntropy(e,t,i){const s=[],n=/['"`]([A-Za-z0-9+/=_\-]{20,})['"`]/g;for(let r=0;r<t.length;r++){const o=t[r];if(this._shouldSkipLine(o,i))continue;let a;for(n.lastIndex=0;null!==(a=n.exec(o));){const t=a[1];if(t.length<this.config.minEntropyLength)continue;if(!/[A-Z]/.test(t)||!/[a-z]/.test(t)||!/[0-9]/.test(t))continue;const i=this._calculateEntropy(t);i>=this.config.entropyThreshold&&s.push(this._createIssue({file:e,line:r+1,column:a.index,type:"High Entropy Secret Candidate",severity:"medium",recommendation:"Review this value, move it to a cloud secret manager if it is a credential, and reference it via environment variables.",id:"SECRET_ENTROPY",match:t,category:"secret",extraMessage:`High-entropy string detected (entropy ${i.toFixed(2)})`}))}}return s}_createIssue({file:e,line:t,column:i,type:s,severity:n,recommendation:r,id:o,match:a,category:c,extraMessage:l}){return{file:e,line:t,column:i,category:c,severity:n,id:o,type:s,recommendation:r,message:l||`${s} detected`,code:"string"==typeof a?a.slice(0,140):""}}async _discoverFiles(e,t=[]){let i=[];try{i=fs.readdirSync(e,{withFileTypes:!0})}catch{return t}for(const s of i){const i=path.join(e,s.name),n=path.relative(this.config.rootPath,i).replace(/\\/g,"/");if(this._shouldIgnore(n))continue;if(s.isDirectory()){await this._discoverFiles(i,t);continue}if(!s.isFile())continue;const r=path.extname(s.name).toLowerCase();(this.scanExtensions.has(r)||s.name.startsWith(".env"))&&t.push(i)}return t}_shouldIgnore(e){const t=e.replace(/\\/g,"/"),i=this.ignoredDirectories;for(const e of i)if(t===e||t.startsWith(`${e}/`)||t.includes(`/${e}/`))return!0;return this.config.ignorePatterns.some(e=>{const i=e.replace(/\\/g,"/"),s=i.replace(/\./g,"\\.").replace(/\*\*/g,".*").replace(/\*/g,"[^/]*");return new RegExp(`^${s}$`).test(t)||t.startsWith(i.replace("/**",""))})}_shouldSkipLine(e,t,i=null){if(!e||!e.trim())return!0;const s=(t||"").replace(/\\/g,"/").toLowerCase();return!!(s.includes("__tests__")||s.includes("/test/")||s.includes("/tests/")||s.endsWith(".spec.js")||s.endsWith(".test.js")||s.endsWith(".spec.ts")||s.endsWith(".test.ts")||s.endsWith(".example")||s.endsWith(".env.example"))||(!i||"SECRET015"!==i.id)&&this.safeLinePatterns.some(t=>t.test(e))}_calculateEntropy(e){const t=new Map;for(const i of e)t.set(i,(t.get(i)||0)+1);let i=0;for(const s of t.values()){const t=s/e.length;i-=t*Math.log2(t)}return i}_isLikelyPlaceholder(e){return!!e&&[/replace[_-\s]?me/i,/replace[_-\s]?with/i,/example/i,/dummy/i,/placeholder/i,/changeme/i,/your[_-\s]?(key|secret|token|password)/i,/local-dev-token/i,/x{8,}/i].some(t=>t.test(e))}_isGitIgnored(e){try{return execFileSync("git",["check-ignore",e],{cwd:this.config.rootPath,stdio:"ignore"}),!0}catch{return!1}}_dedupeIssues(e){const t=new Set;return e.filter(e=>{const i=crypto.createHash("sha1").update(JSON.stringify([e.file,e.line,e.id,e.code,e.commit||""])).digest("hex");return!t.has(i)&&(t.add(i),!0)})}_summarizeIssues(e){return{total:e.length,bySeverity:{critical:e.filter(e=>"critical"===e.severity).length,high:e.filter(e=>"high"===e.severity).length,medium:e.filter(e=>"medium"===e.severity).length},byType:e.reduce((e,t)=>(e[t.type]=(e[t.type]||0)+1,e),{})}}}module.exports=SecretScanner;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const fs=require("fs"),path=require("path"),EventEmitter=require("events");let FileWatcher,CodeScanner,DriftDetector,HealthChecker,AlertManager,SecretScanner;class SentinelCore extends EventEmitter{constructor(e={}){super();const t={...e};delete t.__proto__,delete t.constructor,delete t.prototype,this.config={rootPath:t.rootPath||process.cwd(),watchPatterns:t.watchPatterns||["**/*.js","**/*.ts","**/*.json"],ignorePatterns:t.ignorePatterns||["node_modules/**",".git/**","dist/**",".orion/snapshots/**"],scanIntervalHours:t.scanIntervalHours||6,dailyReportHour:t.dailyReportHour||8,weeklyReportDay:t.weeklyReportDay||1,enableRealtime:!1!==t.enableRealtime,enableScheduled:!1!==t.enableScheduled,alertThreshold:t.alertThreshold||"warning"},this.state={isRunning:!1,lastFullScan:null,lastHealthCheck:null,lastDriftCheck:null,filesWatched:0,issuesFound:[],metrics:{totalScans:0,issuesDetected:0,issuesResolved:0,averageScanTime:0}},this.components={fileWatcher:null,codeScanner:null,driftDetector:null,healthChecker:null,alertManager:null},this.scheduledJobs=[]}async initialize(){console.log("[SENTINEL] Initializing Sentinel Core...");try{return FileWatcher=require("./file-watcher.js"),CodeScanner=require("./code-scanner.js"),DriftDetector=require("./drift-detector.js"),HealthChecker=require("./health-checker.js"),AlertManager=require("./alert-manager.js"),SecretScanner=require("./secret-scanner.js"),this.components.fileWatcher=new FileWatcher(this.config),this.components.codeScanner=new CodeScanner(this.config),this.components.driftDetector=new DriftDetector(this.config),this.components.healthChecker=new HealthChecker(this.config),this.components.alertManager=new AlertManager(this.config),this.components.secretScanner=new SecretScanner(this.config),this._setupEventHandlers(),console.log("[SENTINEL] All components initialized"),{success:!0}}catch(e){return console.error("[SENTINEL] Initialization failed"),{success:!1,error:"Initialization failed"}}}async start(){if(this.state.isRunning)return console.log("[SENTINEL] Already running"),{success:!0,message:"Already running"};console.log("[SENTINEL] Starting Sentinel monitoring...");try{this.config.enableRealtime&&this.components.fileWatcher&&(await this.components.fileWatcher.start(),this.state.filesWatched=this.components.fileWatcher.getWatchedCount()),this.config.enableScheduled&&this._setupScheduledJobs(),await this.runHealthCheck();const e=await this.runFullScan();return this.state.isRunning=!0,this.emit("started",{timestamp:(new Date).toISOString()}),console.log("[SENTINEL] Monitoring active"),console.log(`[SENTINEL] Watching ${this.state.filesWatched} files`),console.log(`[SENTINEL] Initial scan found ${e.issues?.length||0} issues`),{success:!0,filesWatched:this.state.filesWatched,initialIssues:e.issues?.length||0}}catch(e){return console.error("[SENTINEL] Start failed"),{success:!1,error:"Start failed"}}}async stop(){return this.state.isRunning?(console.log("[SENTINEL] Stopping Sentinel monitoring..."),this.components.fileWatcher&&await this.components.fileWatcher.stop(),this.scheduledJobs.forEach(e=>clearInterval(e)),this.scheduledJobs=[],this.state.isRunning=!1,this.emit("stopped",{timestamp:(new Date).toISOString()}),console.log("[SENTINEL] Monitoring stopped"),{success:!0}):{success:!0,message:"Not running"}}async runFullScan(e={}){const t=Date.now();console.log("[SENTINEL] Starting full codebase scan...");const s={timestamp:(new Date).toISOString(),duration:0,filesScanned:0,issues:[],summary:{}};try{if(!this.components.codeScanner)throw new Error("Code scanner not initialized");const e=await this.components.codeScanner.scanAll();if(s.filesScanned=e.filesScanned||0,s.issues.push(...e.issues||[]),this.components.secretScanner){const e=await this.components.secretScanner.scanAll();s.filesScanned+=e.filesScanned||0,s.issues.push(...e.issues||[])}if(this.components.driftDetector){const e=await this.components.driftDetector.detectAll();s.issues.push(...e.issues||[]),this.state.lastDriftCheck=(new Date).toISOString()}return s.duration=Date.now()-t,this.state.lastFullScan=s.timestamp,this.state.metrics.totalScans++,this.state.metrics.issuesDetected+=s.issues.length,this.state.metrics.averageScanTime=(this.state.metrics.averageScanTime*(this.state.metrics.totalScans-1)+s.duration)/this.state.metrics.totalScans,s.summary=this._generateScanSummary(s.issues),this.state.issuesFound=s.issues,await this._processIssues(s.issues),console.log(`[SENTINEL] Scan complete: ${s.filesScanned} files, ${s.issues.length} issues, ${s.duration}ms`),this.emit("scanComplete",s),s}catch(e){return console.error("[SENTINEL] Full scan failed"),s.error="Scan failed",s}}async runQuickScan(e){if(!this.components.codeScanner)return{success:!1,error:"Code scanner not initialized"};console.log(`[SENTINEL] Quick scan on ${e.length} files...`);const t=await this.components.codeScanner.scanFiles(e);return t.issues&&t.issues.length>0&&await this._processIssues(t.issues),t}async runHealthCheck(){if(console.log("[SENTINEL] Running health check..."),!this.components.healthChecker)return{success:!1,error:"Health checker not initialized"};const e=await this.components.healthChecker.checkAll();return this.state.lastHealthCheck=(new Date).toISOString(),e.unhealthySystems&&e.unhealthySystems.length>0&&await(this.components.alertManager?.sendAlert({level:"warning",title:"System Health Issues Detected",message:`${e.unhealthySystems.length} systems are unhealthy`,details:e.unhealthySystems})),this.emit("healthCheck",e),e}async generateDailyDigest(){console.log("[SENTINEL] Generating daily digest...");const e={date:(new Date).toISOString().split("T")[0],timestamp:(new Date).toISOString(),summary:{issuesFound:this.state.issuesFound.length,criticalIssues:this.state.issuesFound.filter(e=>"critical"===e.severity).length,warningIssues:this.state.issuesFound.filter(e=>"warning"===e.severity).length,filesWatched:this.state.filesWatched,lastScan:this.state.lastFullScan,lastHealthCheck:this.state.lastHealthCheck},topIssues:this.state.issuesFound.sort((e,t)=>this._severityScore(t.severity)-this._severityScore(e.severity)).slice(0,10),metrics:this.state.metrics,recommendations:this._generateRecommendations()};return this.components.alertManager&&await this.components.alertManager.sendDigest(e),this.emit("dailyDigest",e),e}async generateWeeklyReport(){console.log("[SENTINEL] Generating weekly report...");const e={weekOf:(new Date).toISOString().split("T")[0],timestamp:(new Date).toISOString(),summary:this.state.metrics,issuesTrend:this._calculateTrend(),codeQuality:await this._assessCodeQuality(),technicalDebt:await this._assessTechnicalDebt(),recommendations:this._generateRecommendations(),fullIssueList:this.state.issuesFound};return this.components.alertManager&&await this.components.alertManager.sendWeeklyReport(e),this.emit("weeklyReport",e),e}getStatus(){return{isRunning:this.state.isRunning,config:this.config,state:{...this.state,componentsLoaded:{fileWatcher:!!this.components.fileWatcher,codeScanner:!!this.components.codeScanner,driftDetector:!!this.components.driftDetector,healthChecker:!!this.components.healthChecker,alertManager:!!this.components.alertManager}},uptime:this.state.isRunning?Date.now()-new Date(this.state.lastFullScan).getTime():0}}getIssues(e={}){let t=[...this.state.issuesFound];return e.severity&&(t=t.filter(t=>t.severity===e.severity)),e.category&&(t=t.filter(t=>t.category===e.category)),e.file&&(t=t.filter(t=>t.file&&t.file.includes(e.file))),t}_setupEventHandlers(){this.components.fileWatcher&&(this.components.fileWatcher.on("change",async e=>{console.log(`[SENTINEL] File changed: ${e.filePath}`),await this.runQuickScan([e.filePath])}),this.components.fileWatcher.on("error",e=>{console.error("[SENTINEL] File watcher error:",e)})),this.components.codeScanner&&this.components.codeScanner.on("issueFound",async e=>{await this._processIssues([e])})}_setupScheduledJobs(){const e=60*this.config.scanIntervalHours*60*1e3;this.scheduledJobs.push(setInterval(()=>this.runFullScan(),e)),this.scheduledJobs.push(setInterval(()=>this.runHealthCheck(),36e5)),this.scheduledJobs.push(setInterval(()=>{const e=new Date;e.getHours()===this.config.dailyReportHour&&e.getMinutes()<5&&this.generateDailyDigest()},36e5)),this.scheduledJobs.push(setInterval(()=>{const e=new Date;e.getDay()===this.config.weeklyReportDay&&e.getHours()===this.config.dailyReportHour&&e.getMinutes()<5&&this.generateWeeklyReport()},36e5)),console.log(`[SENTINEL] Scheduled jobs: scan every ${this.config.scanIntervalHours}h, daily digest at ${this.config.dailyReportHour}:00`)}async _processIssues(e){for(const t of e)this._meetsThreshold(t.severity)&&this.components.alertManager&&await this.components.alertManager.sendAlert({level:t.severity,title:`[${t.category}] ${t.title||t.message}`,message:t.message,file:t.file,line:t.line,details:t})}_meetsThreshold(e){const t=["info","warning","error","critical"];return t.indexOf(e)>=t.indexOf(this.config.alertThreshold)}_severityScore(e){return{info:1,warning:2,error:3,critical:4}[e]||0}_generateScanSummary(e){return{total:e.length,bySeverity:{critical:e.filter(e=>"critical"===e.severity).length,error:e.filter(e=>"error"===e.severity).length,warning:e.filter(e=>"warning"===e.severity).length,info:e.filter(e=>"info"===e.severity).length},byCategory:e.reduce((e,t)=>(e[t.category]=(e[t.category]||0)+1,e),{})}}_generateRecommendations(){const e=[],t=this.state.issuesFound,s=t.filter(e=>"security"===e.category);s.length>0&&e.push({priority:"high",category:"security",message:`Address ${s.length} security issues before deploying`,issues:s.slice(0,5)});const n=t.filter(e=>"quality"===e.category);n.length>10&&e.push({priority:"medium",category:"quality",message:`Consider refactoring - ${n.length} quality issues detected`,issues:n.slice(0,5)});const i=t.filter(e=>"drift"===e.category);return i.length>0&&e.push({priority:"medium",category:"drift",message:`${i.length} files have drifted from their declared contracts`,issues:i.slice(0,5)}),e}_calculateTrend(){return{direction:"stable",change:0,note:"Trend analysis requires historical data"}}async _assessCodeQuality(){return{score:75,grade:"B",factors:{complexity:70,maintainability:80,documentation:65,testCoverage:40}}}async _assessTechnicalDebt(){return{estimatedHours:40,categories:{refactoring:20,documentation:10,testing:10},priorityItems:[]}}}function createSentinel(e={}){return new SentinelCore(e)}async function main(){const e=createSentinel({rootPath:path.resolve(__dirname,".."),enableRealtime:!0,enableScheduled:!1}),t=await e.initialize();t.success||(console.error("Failed to initialize Sentinel:",t.error),process.exit(1)),await e.start(),console.log("Sentinel status:",e.getStatus()),process.on("SIGINT",async()=>{console.log("\nShutting down Sentinel..."),await e.stop(),process.exit(0)})}require.main===module&&main().catch(console.error),module.exports={SentinelCore:SentinelCore,createSentinel:createSentinel};
|