@dailephd/my-dev-kit-lab 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +269 -47
  2. package/dist/scripts/audits/runAudit.js +28 -1
  3. package/dist/scripts/security/validate.js +38 -5
  4. package/dist/src/audits/core/auditConfig.js +16 -1
  5. package/dist/src/audits/core/auditRunner.js +6 -2
  6. package/dist/src/audits/report/auditReportModel.js +7 -0
  7. package/dist/src/audits/report/renderAuditJsonReport.js +1 -0
  8. package/dist/src/audits/report/renderAuditTextReport.js +37 -0
  9. package/dist/src/audits/security/androidAuditIntegration.js +145 -0
  10. package/dist/src/audits/security/mapAndroidSecurityFindingToAuditIssue.js +116 -0
  11. package/dist/src/audits/security/mapSecurityFindingToAuditIssue.js +15 -5
  12. package/dist/src/audits/security/securityAuditAdapter.js +20 -2
  13. package/dist/src/audits/security/securityAuditTypes.js +37 -0
  14. package/dist/src/mobile/android/advancedSecurity/backupConfiguration/analyzeBackupConfiguration.js +300 -0
  15. package/dist/src/mobile/android/advancedSecurity/backupConfiguration/checkResult.js +41 -0
  16. package/dist/src/mobile/android/advancedSecurity/backupConfiguration/index.js +8 -0
  17. package/dist/src/mobile/android/advancedSecurity/backupConfiguration/manifestEvidence.js +102 -0
  18. package/dist/src/mobile/android/advancedSecurity/backupConfiguration/parseBackupRules.js +110 -0
  19. package/dist/src/mobile/android/advancedSecurity/backupConfiguration/types.js +27 -0
  20. package/dist/src/mobile/android/advancedSecurity/candidateEvidence.js +50 -0
  21. package/dist/src/mobile/android/advancedSecurity/clipboard/analyzeClipboardSecurity.js +166 -0
  22. package/dist/src/mobile/android/advancedSecurity/clipboard/checkResult.js +74 -0
  23. package/dist/src/mobile/android/advancedSecurity/clipboard/collectClipboardEvidence.js +82 -0
  24. package/dist/src/mobile/android/advancedSecurity/clipboard/index.js +1 -0
  25. package/dist/src/mobile/android/advancedSecurity/clipboard/types.js +1 -0
  26. package/dist/src/mobile/android/advancedSecurity/externalTools/androidLint/checkResult.js +255 -0
  27. package/dist/src/mobile/android/advancedSecurity/externalTools/androidLint/index.js +1 -0
  28. package/dist/src/mobile/android/advancedSecurity/externalTools/androidLint/parseLintSarif.js +37 -0
  29. package/dist/src/mobile/android/advancedSecurity/externalTools/androidLint/parseLintXml.js +36 -0
  30. package/dist/src/mobile/android/advancedSecurity/externalTools/artifacts.js +95 -0
  31. package/dist/src/mobile/android/advancedSecurity/externalTools/boundedOutput.js +33 -0
  32. package/dist/src/mobile/android/advancedSecurity/externalTools/dependencyCheck/checkResult.js +173 -0
  33. package/dist/src/mobile/android/advancedSecurity/externalTools/dependencyCheck/command.js +33 -0
  34. package/dist/src/mobile/android/advancedSecurity/externalTools/dependencyCheck/index.js +1 -0
  35. package/dist/src/mobile/android/advancedSecurity/externalTools/dependencyCheck/parseDependencyCheckJson.js +133 -0
  36. package/dist/src/mobile/android/advancedSecurity/externalTools/discoverExecutable.js +13 -0
  37. package/dist/src/mobile/android/advancedSecurity/externalTools/index.js +8 -0
  38. package/dist/src/mobile/android/advancedSecurity/externalTools/minimalEnvironment.js +26 -0
  39. package/dist/src/mobile/android/advancedSecurity/externalTools/mutation.js +77 -0
  40. package/dist/src/mobile/android/advancedSecurity/externalTools/osv/checkResult.js +161 -0
  41. package/dist/src/mobile/android/advancedSecurity/externalTools/osv/command.js +25 -0
  42. package/dist/src/mobile/android/advancedSecurity/externalTools/osv/index.js +1 -0
  43. package/dist/src/mobile/android/advancedSecurity/externalTools/osv/parseOsvJson.js +136 -0
  44. package/dist/src/mobile/android/advancedSecurity/externalTools/runBoundedExternalTool.js +51 -0
  45. package/dist/src/mobile/android/advancedSecurity/externalTools/runRequestedAndroidExternalTools.js +54 -0
  46. package/dist/src/mobile/android/advancedSecurity/externalTools/semgrep/checkResult.js +170 -0
  47. package/dist/src/mobile/android/advancedSecurity/externalTools/semgrep/command.js +28 -0
  48. package/dist/src/mobile/android/advancedSecurity/externalTools/semgrep/index.js +2 -0
  49. package/dist/src/mobile/android/advancedSecurity/externalTools/semgrep/parseSemgrepJson.js +141 -0
  50. package/dist/src/mobile/android/advancedSecurity/externalTools/semgrep/rules.js +105 -0
  51. package/dist/src/mobile/android/advancedSecurity/externalTools/types.js +107 -0
  52. package/dist/src/mobile/android/advancedSecurity/fileProvider/checkResult.js +188 -0
  53. package/dist/src/mobile/android/advancedSecurity/fileProvider/index.js +1 -0
  54. package/dist/src/mobile/android/advancedSecurity/firebaseGoogle/analyzeFirebaseGoogleServices.js +197 -0
  55. package/dist/src/mobile/android/advancedSecurity/firebaseGoogle/checkResult.js +77 -0
  56. package/dist/src/mobile/android/advancedSecurity/firebaseGoogle/collectFirebaseServiceEvidence.js +193 -0
  57. package/dist/src/mobile/android/advancedSecurity/firebaseGoogle/discoverFirebaseArtifacts.js +128 -0
  58. package/dist/src/mobile/android/advancedSecurity/firebaseGoogle/index.js +1 -0
  59. package/dist/src/mobile/android/advancedSecurity/firebaseGoogle/parseDatabaseRules.js +55 -0
  60. package/dist/src/mobile/android/advancedSecurity/firebaseGoogle/parseFirebaseConfig.js +75 -0
  61. package/dist/src/mobile/android/advancedSecurity/firebaseGoogle/parseFirestoreStorageRules.js +88 -0
  62. package/dist/src/mobile/android/advancedSecurity/firebaseGoogle/parseGoogleServicesConfig.js +55 -0
  63. package/dist/src/mobile/android/advancedSecurity/firebaseGoogle/types.js +6 -0
  64. package/dist/src/mobile/android/advancedSecurity/networkSecurity/analyzeNetworkSecurity.js +394 -0
  65. package/dist/src/mobile/android/advancedSecurity/networkSecurity/checkResult.js +47 -0
  66. package/dist/src/mobile/android/advancedSecurity/networkSecurity/deriveEffectiveNetworkPolicy.js +52 -0
  67. package/dist/src/mobile/android/advancedSecurity/networkSecurity/index.js +14 -0
  68. package/dist/src/mobile/android/advancedSecurity/networkSecurity/manifestEvidence.js +109 -0
  69. package/dist/src/mobile/android/advancedSecurity/networkSecurity/parseNetworkSecurityConfig.js +186 -0
  70. package/dist/src/mobile/android/advancedSecurity/networkSecurity/types.js +1 -0
  71. package/dist/src/mobile/android/advancedSecurity/ordering.js +44 -0
  72. package/dist/src/mobile/android/advancedSecurity/redaction.js +54 -0
  73. package/dist/src/mobile/android/advancedSecurity/releaseConfiguration/analyzeReleaseConfiguration.js +221 -0
  74. package/dist/src/mobile/android/advancedSecurity/releaseConfiguration/checkResult.js +39 -0
  75. package/dist/src/mobile/android/advancedSecurity/releaseConfiguration/index.js +7 -0
  76. package/dist/src/mobile/android/advancedSecurity/releaseConfiguration/manifestEvidence.js +19 -0
  77. package/dist/src/mobile/android/advancedSecurity/resourceReference.js +69 -0
  78. package/dist/src/mobile/android/advancedSecurity/resourceResolution.js +118 -0
  79. package/dist/src/mobile/android/advancedSecurity/ruleIds.js +141 -0
  80. package/dist/src/mobile/android/advancedSecurity/secretCandidates/analyzeSecretCandidates.js +116 -0
  81. package/dist/src/mobile/android/advancedSecurity/secretCandidates/checkResult.js +80 -0
  82. package/dist/src/mobile/android/advancedSecurity/secretCandidates/discoverSecretSourceFiles.js +152 -0
  83. package/dist/src/mobile/android/advancedSecurity/secretCandidates/index.js +9 -0
  84. package/dist/src/mobile/android/advancedSecurity/secretCandidates/matchSecretCandidates.js +136 -0
  85. package/dist/src/mobile/android/advancedSecurity/secretCandidates/suppressValue.js +61 -0
  86. package/dist/src/mobile/android/advancedSecurity/secretCandidates/types.js +11 -0
  87. package/dist/src/mobile/android/advancedSecurity/sensitiveCategories.js +34 -0
  88. package/dist/src/mobile/android/advancedSecurity/sensitiveData/classifyDirectExpression.js +99 -0
  89. package/dist/src/mobile/android/advancedSecurity/sensitiveData/classifySensitiveIdentifier.js +111 -0
  90. package/dist/src/mobile/android/advancedSecurity/sensitiveData/index.js +3 -0
  91. package/dist/src/mobile/android/advancedSecurity/sensitiveData/localSourceContext.js +90 -0
  92. package/dist/src/mobile/android/advancedSecurity/sensitiveData/splitArguments.js +59 -0
  93. package/dist/src/mobile/android/advancedSecurity/sensitiveLogging/analyzeSensitiveLogging.js +117 -0
  94. package/dist/src/mobile/android/advancedSecurity/sensitiveLogging/checkResult.js +74 -0
  95. package/dist/src/mobile/android/advancedSecurity/sensitiveLogging/collectLoggingEvidence.js +87 -0
  96. package/dist/src/mobile/android/advancedSecurity/sensitiveLogging/index.js +1 -0
  97. package/dist/src/mobile/android/advancedSecurity/sensitiveLogging/types.js +1 -0
  98. package/dist/src/mobile/android/advancedSecurity/sensitiveStorage/analyzeSensitiveStorage.js +182 -0
  99. package/dist/src/mobile/android/advancedSecurity/sensitiveStorage/checkResult.js +74 -0
  100. package/dist/src/mobile/android/advancedSecurity/sensitiveStorage/collectStorageEvidence.js +109 -0
  101. package/dist/src/mobile/android/advancedSecurity/sensitiveStorage/index.js +1 -0
  102. package/dist/src/mobile/android/advancedSecurity/sensitiveStorage/types.js +4 -0
  103. package/dist/src/mobile/android/advancedSecurity/signingConfiguration/analyzeSigningConfiguration.js +270 -0
  104. package/dist/src/mobile/android/advancedSecurity/signingConfiguration/checkResult.js +119 -0
  105. package/dist/src/mobile/android/advancedSecurity/signingConfiguration/discoverKeystoreCandidates.js +55 -0
  106. package/dist/src/mobile/android/advancedSecurity/signingConfiguration/extractSigningConfigurations.js +81 -0
  107. package/dist/src/mobile/android/advancedSecurity/signingConfiguration/index.js +8 -0
  108. package/dist/src/mobile/android/advancedSecurity/signingConfiguration/types.js +20 -0
  109. package/dist/src/mobile/android/advancedSecurity/sourceLocation.js +15 -0
  110. package/dist/src/mobile/android/advancedSecurity/webview/checkResult.js +210 -0
  111. package/dist/src/mobile/android/advancedSecurity/webview/index.js +1 -0
  112. package/dist/src/mobile/android/gradle/moduleMetadataExtractor.js +123 -17
  113. package/dist/src/mobile/android/manifest/parseAndroidManifest.js +27 -4
  114. package/dist/src/mobile/android/manifest/xml/parseXml.js +25 -9
  115. package/dist/src/mobile/android/report/model.js +32 -1
  116. package/dist/src/mobile/android/report/renderAndroidReport.js +63 -0
  117. package/dist/src/mobile/android/validate/validateAndroidTarget.js +146 -3
  118. package/dist/src/mobile/android/validation/checkResult.js +7 -0
  119. package/dist/src/securityValidation/commandRunner.js +10 -1
  120. package/dist/src/securityValidation/validate/cliOptions.js +46 -0
  121. package/package.json +1 -1
  122. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/debug/res/xml/ambiguous_backup_rules.xml +4 -0
  123. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/main/res/xml/ambiguous_backup_rules.xml +4 -0
  124. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/main/res/xml/backup_rules.xml +5 -0
  125. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/main/res/xml/broad_backup_rules.xml +4 -0
  126. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/main/res/xml/data_extraction_rules.xml +10 -0
  127. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/main/res/xml/unsupported_domain_rules.xml +4 -0
  128. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-b/src/main/res/xml/malformed_backup_rules.xml +4 -0
  129. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-b/src/main/res/xml/unsupported_root.xml +4 -0
  130. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/debug/res/xml/ambiguous_config.xml +4 -0
  131. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/ambiguous_config.xml +4 -0
  132. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/base_cleartext_false.xml +8 -0
  133. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/broad_and_duplicate_domains.xml +8 -0
  134. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/empty_domain.xml +6 -0
  135. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/malformed_pin.xml +11 -0
  136. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/network_security_config.xml +26 -0
  137. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-b/src/main/res/xml/malformed_network_security_config.xml +6 -0
  138. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-b/src/main/res/xml/unsupported_root.xml +4 -0
  139. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/groovy-release-debuggable-dynamic.gradle +7 -0
  140. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/groovy-release-debuggable-false.gradle +9 -0
  141. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/groovy-release-debuggable-true.gradle +13 -0
  142. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/kotlin-release-debuggable-false.gradle.kts +7 -0
  143. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/kotlin-release-debuggable-true.gradle.kts +10 -0
  144. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/missing-release-build-type.gradle.kts +7 -0
  145. package/tests/fixtures/android/advanced-security-fixtures/resource-resolution/module-a/src/debug/res/xml/network_security_config.xml +8 -0
  146. package/tests/fixtures/android/advanced-security-fixtures/resource-resolution/module-a/src/main/res/xml/backup_rules.xml +4 -0
  147. package/tests/fixtures/android/advanced-security-fixtures/resource-resolution/module-a/src/main/res/xml/network_security_config.xml +8 -0
  148. package/tests/fixtures/android/advanced-security-fixtures/resource-resolution/module-b/src/main/res/xml/malformed_network_security_config.xml +7 -0
  149. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/SampleActivity.java +8 -0
  150. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/SampleActivity.kt +9 -0
  151. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/build.gradle +11 -0
  152. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/build.gradle.kts +11 -0
  153. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/google-services.json +16 -0
  154. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/local.properties +3 -0
  155. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates-bounds/module/binary.properties +0 -0
  156. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates-bounds/module/oversized.json +1 -0
  157. package/tests/fixtures/android/advanced-security-fixtures/signing-configuration/app/fake-release-keystore.jks +1 -0
  158. package/tests/fixtures/android/advanced-security-fixtures/signing-configuration/build/generated-fake.keystore +1 -0
package/README.md CHANGED
@@ -1,78 +1,300 @@
1
1
  # my-dev-kit-lab
2
2
 
3
- my-dev-kit-lab is the experiment, evidence, reporting, visualization, and security-validation companion for my-dev-kit. It provides controlled raw-full-file versus graph-guided retrieval experiments, deterministic fake-agent demonstrations, reports, plots, gallery artifacts, generic audits, and local security-validation workflows.
3
+ > Current release state: v0.4.1 is the latest published baseline. v0.4.0 delivered the Android validation MVP; v0.4.1 delivered advanced Android security. v0.4.2 is implemented and release-prepared (package metadata `0.4.2`) but not yet published. Manual pentest is post-v1 / version TBD.
4
4
 
5
- The current published baseline is `v0.3.4`. The v0.4.0 Android validation implementation is release-prepared on `release/v0.4.0`; publication is pending. It is not published, and the npm registry latest version remains `0.3.4`.
5
+ my-dev-kit-lab is the experiment, evidence, reporting, security-validation, and audit companion for my-dev-kit. It runs reproducible experiments that test whether my-dev-kit's graph-guided retrieval helps coding-agent workflows, collects metrics, renders reports, generates plots, captures screenshots, builds gallery outputs, performs automated CLI/package security validation, and runs the generic audit framework.
6
+
7
+ The generic experiment-plugin framework was introduced in `v0.2.0`. Its first plugin, `context-strategy-comparison`, preserves the raw-full-file vs my-dev-kit-guided comparison through the plugin runner. Later releases added the generic audit framework, language-aware code-rot detectors for TypeScript/JavaScript, Python, Java, and Kotlin, a security-validation audit adapter, and Android validation. See [CHANGELOG.md](CHANGELOG.md) for the complete release history.
8
+
9
+ my-dev-kit is most useful when the repository is larger than the task. It helps coding agents work with large codebases through reusable structural indexing, graph-guided retrieval, targeted source slices, and auditable context selection. Results are scoped evidence; the project does not claim that my-dev-kit always saves tokens.
10
+
11
+ **my-dev-kit** is the repo indexing and graph-guided retrieval engine.
12
+ **my-dev-kit-lab** is the separate lab layer that feeds it benchmark inputs and records evaluation outputs.
13
+
14
+ ---
6
15
 
7
16
  ## Current capabilities
8
17
 
9
- - Controlled experiment plugins, reports, plots, screenshots, and gallery artifacts.
10
- - Generic code-rot and general security audit types through `npm run audit`.
11
- - Standalone CLI/package security validation through `npm run security:validate`.
12
- - Android security validation through the canonical `android` profile on the v0.4.0 feature branch.
18
+ - Benchmark projects at small, medium, and large complexity levels
19
+ - Project complexity metrics and benchmark case metadata with answer keys
20
+ - Prompt variant generation at `short`, `medium`, `long`, and `multi-step` complexity levels
21
+ - Fake-agent adapter for deterministic smoke and demo validation
22
+ - Codex and Claude adapters for real-agent campaigns
23
+ - Controlled experiment runner comparing `raw-full-file` vs `my-dev-kit-guided` strategies
24
+ - Deterministic correctness scoring from answer keys
25
+ - Token usage, duration, and status comparisons between matched strategy pairs
26
+ - HTML experiment report rendering
27
+ - Static SVG plot generation
28
+ - Optional PNG screenshot capture
29
+ - Gallery manifest and static gallery index output
30
+ - Visualization demos using my-dev-kit commands against benchmark projects
31
+ - Final demo workflow combining all pipeline stages
32
+ - Generic experiment-plugin command surface: `experiment:list`, `experiment:describe`, and `experiment:run`
33
+ - First experiment plugin: `context-strategy-comparison`
34
+ - Target-aware experiment execution for local projects via `experiment:run -- --target <path>`
35
+ - Plugin-aware JSON and HTML reports with plugin, target, variant, metric, artifact, warning, skip, and failure metadata
36
+ - Security validation framework: dependency audit, package tarball inspection, CLI adversarial tests, static scans (CodeQL/Semgrep), bounded fuzz smoke, attack-scenario checks, and structured verdict/report output — runnable against any local project via `security:validate --target <path>`. `security:validate` remains the standalone, focused security-validation command; it is not replaced by the audit adapter below.
37
+ - Generic audit framework: `npm run audit` runs conservative code-rot and security detectors and writes text/JSON reports under `reports/audits/` by default. `code-rot` and `security` are the currently implemented audit types (`--types code-rot`, `--types security`, or combined `--types code-rot,security`); `quality`, `project`, and `all` audit types are planned and fail cleanly instead of running. Audit does not modify target files and does not auto-fix issues. See [docs/COMMANDS.md](docs/COMMANDS.md) for full flags.
38
+ - Language-aware code-rot detectors for TypeScript/JavaScript, Python, Java, and Kotlin, built on a shared source-facts model and normalized language/file-role inventory. Java/Kotlin support is conservative static analysis only: no compiler parsing, type/classpath resolution, or Gradle/Maven execution.
39
+ - Security-validation audit adapter: `npm run audit -- --types security` runs the same `security:validate` internals through the shared audit/report surface, mapping findings into audit issues and linking back to the original `reports/security/` report. `security:validate`'s own checks and reports are unaffected.
40
+ - Android validation: `security:validate --profile android` runs nineteen static checks against an Android project (manifest, permissions, exported components, network security config, backup/release configuration, secrets, signing, WebView/FileProvider, sensitive storage/logging, and Firebase/Google services), with optional opt-in Gradle operations and external tools (Semgrep, OSV-Scanner, Android Lint, Dependency-Check). Default execution starts zero Gradle processes, zero external tools, and zero network operations.
41
+ - Android-aware generic audit: `npm run audit -- --types security --android` runs the same static Android validation through the audit adapter, mapping confirmed findings into audit issues while keeping review-only `CandidateEvidence` separate and never treated as a confirmed issue.
13
42
 
14
- ## Android validation
43
+ ---
15
44
 
16
- Run static Android validation with:
45
+ ## Architecture overview
17
46
 
18
- ```powershell
19
- npm run security:validate -- --target "<android-project-path>" --profile android
47
+ ```mermaid
48
+ flowchart TD
49
+ A[scripts/experiments] --> B[Experiment plugin registry + runner]
50
+ B --> C[context-strategy-comparison]
51
+ C --> D[Controlled experiment foundations]
52
+ D --> E[Plugin + legacy artifacts]
53
+ E --> F[Plugin-aware reports]
54
+ E --> G[Plots / screenshots / gallery]
55
+ H[scripts/security] --> I[Automated security validation]
56
+ I --> J[Security reports + verdict]
57
+ I --> K[Android validation]
58
+ L[scripts/audits] --> M[Generic audit framework]
59
+ M --> N[Code-rot detectors]
60
+ M --> I
20
61
  ```
21
62
 
22
- This default path executes **no Gradle commands**. It detects/classifies Android projects and UI evidence, parses discovered manifests independently, audits permissions/exported components/intent filters/deep links, extracts static Gradle metadata, assembles release metadata and Play-readiness placeholders, calculates an Android verdict, and writes bounded text and JSON reports.
63
+ ---
23
64
 
24
- Reports use the existing `reports/security/` root unless `--out` is supplied. Android report files use the `<prefix>-android-security-validation.txt` and `.json` convention.
65
+ ## Quickstart
25
66
 
26
- Optional Gradle validation is explicit:
67
+ ### Install
27
68
 
28
- ```powershell
29
- npm run security:validate -- --target "<android-project-path>" --profile android --android-gradle-operations wrapper-version,tasks
69
+ ```bash
70
+ npm install
71
+ ```
72
+
73
+ The same command works in PowerShell and `cmd.exe`.
74
+
75
+ ### Build
76
+
77
+ ```bash
78
+ npm run build
79
+ ```
80
+
81
+ ### Verify the installation
82
+
83
+ ```bash
84
+ npm run verify
85
+ ```
86
+
87
+ ### Run the fake-agent final demo (deterministic, no external CLIs required)
88
+
89
+ ```bash
90
+ npm run run-final-demo -- \
91
+ --cases examples/token-savings-cases.json \
92
+ --out lab-output/final-demo \
93
+ --kit-command "node tests/fixtures/fake-my-dev-kit-cli.js" \
94
+ --agents fake-agent \
95
+ --complexities short \
96
+ --no-screenshot
30
97
  ```
31
98
 
32
- The only allowed operation IDs are:
99
+ ```powershell
100
+ npm run run-final-demo -- `
101
+ --cases examples/token-savings-cases.json `
102
+ --out lab-output/final-demo `
103
+ --kit-command "node tests/fixtures/fake-my-dev-kit-cli.js" `
104
+ --agents fake-agent `
105
+ --complexities short `
106
+ --no-screenshot
107
+ ```
33
108
 
34
- - `wrapper-version`
35
- - `tasks`
36
- - `assemble-debug`
37
- - `unit-test-debug`
38
- - `lint-debug`
109
+ ```bat
110
+ npm run run-final-demo -- --cases examples/token-savings-cases.json --out lab-output/final-demo --kit-command "node tests/fixtures/fake-my-dev-kit-cli.js" --agents fake-agent --complexities short --no-screenshot
111
+ ```
39
112
 
40
- Unknown or empty lists, arbitrary tasks, and use with a non-Android profile are rejected. Optional operations can require Java, Android SDK components, wrapper distributions, and cached dependencies; environment gaps can produce skipped or inconclusive evidence.
113
+ The lab resolves Windows `.cmd` and `.ps1` CLI shims, supports command paths with spaces, and keeps generated artifacts inside the requested output directory.
41
114
 
42
- ### Verdicts
115
+ This runs a full pipeline: controlled experiment → report → plots → visualization demos → gallery.
43
116
 
44
- - `not-ready-security-blocker-remains`: a blocker remains.
45
- - `inconclusive-audit-environment-incomplete`: required evidence/environment is incomplete.
46
- - `ready-except-optional-manual-checks`: advisory or manual follow-up remains.
47
- - `ready-for-release-preparation`: required static evidence passed.
117
+ ### Run a real-agent campaign (requires Codex or Claude CLI)
48
118
 
49
- These are validation-evidence states, not claims that an app is published, Play-ready, Play-compliant, runtime-secure, or signing-valid.
119
+ ```bash
120
+ npm run run-controlled-experiment -- \
121
+ --cases examples/real-agent-campaign-cases.json \
122
+ --agents codex,claude \
123
+ --strategies raw-full-file,my-dev-kit-guided \
124
+ --complexities medium,multi-step \
125
+ --out lab-output/real-agent-campaign \
126
+ --include-real-agents \
127
+ --continue-on-failure \
128
+ --timeout-ms 240000
129
+ ```
50
130
 
51
- ### Important Android limitations
131
+ Real-agent runs require local Codex or Claude CLI setup and available usage capacity. Runs that time out, produce invalid output, or hit session limits are recorded as structured outcomes rather than failures.
52
132
 
53
- - Static analysis does not prove runtime behavior.
54
- - Manifests are not merged; placeholders and resource references are not resolved.
55
- - Gradle scripts are not evaluated; dynamic metadata can stay unresolved; same-file duplicate assignment extraction uses the first match.
56
- - Optional Gradle execution is disabled by default and environment-dependent.
57
- - APK/AAB contents, signing, emulator/device behavior, Digital Asset Links, domain ownership, and live Google Play policy are not validated.
58
- - Play Console items such as privacy policy, Data Safety, permissions declarations, store listing, release notes, content rating, and policy review remain manual placeholders.
133
+ ### List, describe, and run experiment plugins
59
134
 
60
- ## Development
135
+ ```bash
136
+ npm run experiment:list
137
+ npm run experiment:describe -- --experiment context-strategy-comparison
138
+ npm run experiment:run -- \
139
+ --experiment context-strategy-comparison \
140
+ --target /path/to/local/project \
141
+ --agents fake-agent \
142
+ --complexities short \
143
+ --no-screenshot
144
+ ```
61
145
 
62
146
  ```powershell
63
- npm run typecheck
64
- npm run build
65
- npm run test
66
- npm run verify
147
+ npm run experiment:list
148
+ npm run experiment:describe -- --experiment context-strategy-comparison
149
+ npm run experiment:run -- `
150
+ --experiment context-strategy-comparison `
151
+ --target "Z:\Users\newuser\Projects\my-dev-kit-v1" `
152
+ --agents fake-agent `
153
+ --complexities short `
154
+ --no-screenshot
67
155
  ```
68
156
 
69
- Use `npm run security:validate -- --help` for command usage. Help does not run validation or write reports.
157
+ When `--target` is omitted, the experiment runs in self mode against my-dev-kit-lab. When `--target <path>` is provided, the lab remains the tool root and the target project is inspected separately. Generated experiment outputs stay under lab-controlled output directories by default, not inside the target project.
158
+
159
+ ---
160
+
161
+ ## Where to find outputs
162
+
163
+ | Artifact | Location |
164
+ |---|---|
165
+ | Experiment summary | `lab-output/<experiment>/experiment-summary.json` |
166
+ | All runs | `lab-output/<experiment>/experiment-runs.json` |
167
+ | Strategy comparisons | `lab-output/<experiment>/experiment-comparisons.json` |
168
+ | HTML report | `lab-output/<report>/experiment-report.html` |
169
+ | Report JSON | `lab-output/<report>/experiment-report.json` |
170
+ | Report screenshot | `lab-output/<report>/experiment-report.png` |
171
+ | Plugin experiment report JSON | `lab-output/experiments/<plugin>/<target>/<run>/report.json` |
172
+ | Plugin experiment report HTML | `lab-output/experiments/<plugin>/<target>/<run>/report.html` |
173
+ | Plot data | `lab-output/<plots>/plot-data.json` |
174
+ | SVG charts | `lab-output/<plots>/charts/*.svg` |
175
+ | Gallery manifest | `lab-output/<gallery>/gallery-manifest.json` |
176
+ | Gallery index | `lab-output/<gallery>/gallery-index.html` |
177
+
178
+ ---
179
+
180
+ ## How to read the main report
181
+
182
+ Open `experiment-report.html` in a browser. The report shows:
183
+
184
+ - **Project profile** — benchmark project name, language mix, complexity score, and file tree
185
+ - **Benchmark tasks** — task descriptions and answer keys
186
+ - **Strategy comparisons** — paired `raw-full-file` vs `my-dev-kit-guided` runs per case
187
+ - **Correctness scores** — deterministic answer-key scoring (not semantic LLM judging)
188
+ - **Token usage** — estimated or reported token totals per run
189
+ - **Token savings** — positive means my-dev-kit used fewer tokens; negative means it used more
190
+ - **Duration** — wall-clock time per run
191
+ - **Status** — completed, timeout, invalid-output, or limit-reached
192
+ - **Warnings and limitations** — notes on missing token totals or partial results
193
+
194
+ See [docs/METRICS.md](docs/METRICS.md) for full metric definitions.
195
+
196
+ ---
197
+
198
+ ## Current limitations
199
+
200
+ - Token savings shown in fake-agent runs are based on estimated character counts, not provider billing telemetry
201
+ - Claude does not expose token totals; token savings comparisons are unavailable for Claude runs
202
+ - Codex may expose token totals but can produce timeouts or invalid-output runs
203
+ - Small projects may make raw-full-file cheaper than my-dev-kit-guided; larger localized tasks are where my-dev-kit is expected to become more useful
204
+ - The generic experiment-plugin framework currently ships one plugin, `context-strategy-comparison`; future plugins such as warm-index reuse, incremental-change, and context-window scaling are not implemented yet
205
+ - The current baseline does not prove token savings are guaranteed; it produces auditable evidence for specific cases, targets, agents, and strategies
206
+ - Provider telemetry dashboards, semantic LLM judging, and cloud API billing integration are not yet implemented
207
+
208
+ ---
209
+
210
+ ## Roadmap direction
211
+
212
+ my-dev-kit-lab is at a working baseline. The raw-vs-indexed experiment pipeline is fully implemented and produces reproducible artifacts, and real-agent campaign support exists for Codex and Claude. Recent releases added language-aware code-rot detectors (TypeScript/JavaScript, Python, Java, Kotlin), a security-validation audit adapter, and Android validation with an Android-aware extension of that same adapter.
213
+
214
+ - `v0.4.0` and `v0.4.1`: Android automated security validation (published)
215
+ - `v0.4.2`: Android-aware extension of the existing security audit adapter (see [CHANGELOG.md](CHANGELOG.md) for release status)
216
+ - manual pentest: post-v1 / version TBD
217
+
218
+ See [docs/ROADMAP.md](docs/ROADMAP.md) for the complete, versioned plan.
219
+
220
+ ---
221
+
222
+ ## Security validation
223
+
224
+ my-dev-kit-lab owns a release-security validation track for **my-dev-kit**. This work is separate from the experiment pipeline and does not replace the generic experiment-plugin roadmap. Its purpose is to generate release-validation evidence for the local CLI/package before release preparation.
225
+
226
+ `security:validate` remains the standalone, focused command for this validation and is unaffected by the current checked-out state. `npm run audit -- --types security` additionally adapts the same `security:validate` internals into the shared audit/report surface (mapped issues, a `securitySummary` field, and links to the original `reports/security/` output) — it does not replace or duplicate `security:validate`'s own checks or reports.
227
+
228
+ This is not a web application pentest framework. **my-dev-kit** is a local CLI/package, so the validation model is CLI/package adversarial testing focused on whether it remains:
229
+
230
+ - local-first
231
+ - deterministic
232
+ - read-only with respect to user source files
233
+ - network-free during normal CLI operation
234
+ - LLM-free
235
+ - database-free
236
+ - safe to run on local repositories
237
+
238
+ The automated validation gate is implemented. It combines static scans, dependency/package checks, adversarial CLI tests, bounded fuzz smoke tests, and attack-scenario checks with structured text/JSON reports and a four-category verdict.
239
+
240
+ ### Security commands
241
+
242
+ | Command | Description |
243
+ |---|---|
244
+ | `npm run security:deps` | npm audit, OSV-Scanner (if available), outdated packages |
245
+ | `npm run security:package` | npm pack --dry-run, forbidden content detection |
246
+ | `npm run security:codeql` | CodeQL CLI availability check; skipped gracefully when absent |
247
+ | `npm run security:semgrep` | Semgrep scan via local binary or npx; skipped gracefully when both absent |
248
+ | `npm run test:security` | Automated security and adversarial CLI tests (path traversal, read-only boundaries, malformed artifacts, JSON safety, and related checks) |
249
+ | `npm run test:fuzz:smoke` | 9 bounded fuzz targets, seeded PRNG, completes in under 1 second |
250
+ | `npm run security:validate` | Runs selected security checks, applies profile-aware defaults when requested, and writes text/JSON reports according to `--format` |
251
+
252
+ CodeQL, Semgrep, and OSV-Scanner are optional. When unavailable locally, they are recorded as `skipped` in the report, not as passed. That can lead to `ready except optional manual checks`; it does not silently turn missing tooling into a clean pass.
253
+
254
+ Each security command can validate my-dev-kit-lab itself or another local project via `--target <path>`. When `--target` is omitted, the framework performs self-validation. Target projects are inspected in place: their source files are not modified by default, generated artifacts stay under `reports/security/` unless `--out` is used, and external-target reports identify the tool root, target root, target package metadata, target git metadata, command cwd, exit code, and stdout/stderr summaries.
255
+
256
+ `security:validate` supports `--checks`, `--profile`, `--format`, `--fail-on`, `--out`, and `--report-prefix`. The no-flag path remains backward compatible and still runs the classic implemented check groups: `deps`, `package`, `static`, `cli-adversarial`, and `fuzz`. Supplying `--profile` without `--checks` swaps in that profile's default checks; supplying explicit `--checks` always wins over profile defaults.
257
+
258
+ The current attack-scenario checks cover boundary, subprocess, secrets, and network assumptions. They are automated adversarial checks, not a manual pentest. Manual pentest is deferred until after `v1.0.0`. `verdictImpact` metadata from each registered scenario drives blocker categorization in report reasoning, and narrowed `--checks` runs are labeled as scoped rather than described as a full release gate.
259
+
260
+ JSON report poisoning/config-injection checks use a baseline-diff schema guard so legitimate additive JSON fields do not fail the guard while payload-created trusted top-level fields still do. Text reports are sanitized to strip ANSI/control-byte payloads before rendering.
261
+
262
+ Known limits remain intentionally explicit: secret scanning is bounded rather than exhaustive, the network/local-first check is a bounded static assumption check rather than proof of runtime isolation, package-boundary severity is still result-level rather than per-evidence-item, and profile-specific scenario behavior is limited to profile-based scenario selection/default checks.
263
+
264
+ For external-target validation, `security:validate` reads the target `package.json`, detects `scripts.test:security`, and runs `npm run test:security` in the target project root when that script exists. This behavior is validated both from the source checkout and from an installed packed tarball because published-package execution differs from local source execution.
265
+
266
+ Generated security reports under `reports/security/` are excluded from git by default. They are produced locally or in CI as release-gate evidence and are not committed to the repository.
267
+
268
+ See [docs/COMMANDS.md](docs/COMMANDS.md) for full command options and [docs/security-validation-framework.md](docs/security-validation-framework.md) for the security model, implemented modules, and release verdicts.
269
+
270
+ ---
271
+
272
+ ## License
273
+
274
+ MIT License. See [LICENSE](LICENSE) for the full text.
275
+
276
+ ---
277
+
278
+ ## Support
279
+
280
+ my-dev-kit-lab is an independent project by dailephd LLC, developed and maintained by Dai Le.
281
+
282
+ If this project helps your workflow, you can support continued development through GitHub Sponsors or PayPal:
283
+
284
+ - [Sponsor on GitHub](https://github.com/sponsors/dailephd)
285
+ - [Support via PayPal](https://paypal.me/daile88)
286
+
287
+ Support is optional and does not affect access to the project.
70
288
 
71
- ## Roadmap status
289
+ ---
72
290
 
73
- - `v0.4.0`: Android validation MVP — release-prepared; publication pending.
74
- - `v0.4.1`: planned advanced Android security checks.
75
- - `v0.4.2`: planned Android extension of the existing security audit adapter; it will not replace `security:validate`.
76
- - Manual pentest: deferred post-v1 / version TBD; not part of v0.4.x.
291
+ ## Documentation
77
292
 
78
- See [docs/PROJECT_OVERVIEW.md](docs/PROJECT_OVERVIEW.md), [docs/COMMANDS.md](docs/COMMANDS.md), [docs/WORKFLOWS.md](docs/WORKFLOWS.md), [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), and [docs/ROADMAP.md](docs/ROADMAP.md).
293
+ - [docs/PROJECT_OVERVIEW.md](docs/PROJECT_OVERVIEW.md) — product purpose and target users
294
+ - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — current and future architecture
295
+ - [docs/WORKFLOWS.md](docs/WORKFLOWS.md) — step-by-step workflows with diagrams
296
+ - [docs/COMMANDS.md](docs/COMMANDS.md) — all commands with options and examples
297
+ - [docs/TUTORIAL.md](docs/TUTORIAL.md) — first-run walkthrough
298
+ - [docs/METRICS.md](docs/METRICS.md) — metric definitions and interpretation
299
+ - [docs/ROADMAP.md](docs/ROADMAP.md) — current baseline and future phases
300
+ - [docs/GALLERY.md](docs/GALLERY.md) — gallery output explained
@@ -20,9 +20,29 @@ import { writeAuditReports } from "../../src/audits/report/writeAuditReports.js"
20
20
  // ---------------------------------------------------------------------------
21
21
  const USAGE = "Usage: npm run audit -- [--target <path>] [--types code-rot,security] " +
22
22
  "[--include docs,tests,package,architecture,cli] [--format text,json] " +
23
- "[--fail-on blocker|high|medium|low|none] [--out <path>]";
23
+ "[--fail-on blocker|high|medium|low|none] [--out <path>] [--android]\n" +
24
+ "\n" +
25
+ " --android opts into Batch 2's programmatic Android security integration.\n" +
26
+ " Requires --types to include \"security\" (e.g. --types security or --types\n" +
27
+ " code-rot,security). Runs the same static, read-only, nineteen-check\n" +
28
+ " Android validation security:validate --profile android performs --\n" +
29
+ " detection, manifest parsing, and internal advanced security checks --\n" +
30
+ " through the existing security adapter, never a subprocess. Confirmed\n" +
31
+ " findings are mapped into the normal issue collection; CandidateEvidence\n" +
32
+ " remains a separate, bounded summary and is never treated as a confirmed\n" +
33
+ " issue. Starts zero Gradle operations, zero external tools, and zero\n" +
34
+ " network operations by default; --android does not expose any of those.\n" +
35
+ " Example: npm run audit -- --target \"<android-project-path>\" --types security --android --format text,json --fail-on none";
24
36
  const rawArgs = process.argv.slice(2);
25
37
  const toolRoot = resolveToolRoot(import.meta.url);
38
+ // Help deliberately wins over every other argument, mirroring
39
+ // scripts/security/validate.ts -- no config normalization, target
40
+ // resolution, audit execution, or report write.
41
+ if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
42
+ console.log(USAGE);
43
+ process.exitCode = 0;
44
+ process.exit(0);
45
+ }
26
46
  let config;
27
47
  try {
28
48
  const args = parseAuditArgs(rawArgs);
@@ -89,6 +109,13 @@ if (model.securitySummary.ran) {
89
109
  console.log(` Full report: ${model.securitySummary.reportPaths.text}`);
90
110
  }
91
111
  }
112
+ if (model.androidSecurity.summary.requested) {
113
+ const android = model.androidSecurity.summary;
114
+ console.log(`\nAndroid security validation: status=${android.status} applicable=${android.applicable ?? "n/a"} verdict=${android.verdict ?? "(unknown)"} checks=${android.totalChecks} confirmed=${android.confirmedFindingCount} mappedIssues=${android.mappedIssueCount} candidates=${android.candidateSummary.totalCount}`);
115
+ if (android.reportPaths.text) {
116
+ console.log(` Full report: ${android.reportPaths.text}`);
117
+ }
118
+ }
92
119
  console.log(`\nInventory: ${model.inventory.totalScannedFileCount} file(s) scanned, ${model.inventory.skippedFileCount} skipped`);
93
120
  console.log(` source=${model.inventory.filesByCategory.source} tests=${model.inventory.filesByCategory.tests} docs=${model.inventory.filesByCategory.docs} package=${model.inventory.filesByCategory.package} config=${model.inventory.filesByCategory.config} scripts=${model.inventory.filesByCategory.scripts} ci=${model.inventory.filesByCategory.ci}`);
94
121
  console.log(`Source of truth: package=${model.sourceOfTruth.packageName ?? "(none)"}@${model.sourceOfTruth.packageVersion ?? "?"} readme=${model.sourceOfTruth.hasReadme} changelog=${model.sourceOfTruth.hasChangelog} ciWorkflows=${model.sourceOfTruth.ciWorkflowCount}`);
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import path from "node:path";
2
3
  import { runSecurityValidation } from "../../src/securityValidation/validate/runSecurityValidation.js";
3
4
  import { resolveValidationTarget, reportFilenamePrefix } from "../../src/securityValidation/validate/resolveTarget.js";
4
5
  import { buildSecurityReportFromSummary } from "../../src/securityValidation/report/buildSecurityReport.js";
@@ -15,18 +16,35 @@ import { writeAndroidReportFiles } from "../../src/mobile/android/report/writeAn
15
16
  const USAGE = "Usage: npm run security:validate -- [--target <path>] [--out <dir>] [--report-prefix <name>] " +
16
17
  "[--checks deps,package,static,cli-adversarial,fuzz,boundary,subprocess,secrets,network] " +
17
18
  "[--profile node-cli-package|local-tool|npm-package|android] [--format text,json] [--fail-on blocker|high|medium|low] " +
18
- "[--android-gradle-operations wrapper-version,tasks,assemble-debug,unit-test-debug,lint-debug]\n" +
19
+ "[--android-gradle-operations wrapper-version,tasks,assemble-debug,unit-test-debug,lint-debug] " +
20
+ "[--android-external-tools semgrep,osv,android-lint,dependency-check] " +
21
+ "[--android-external-network deny|allow-requested]\n" +
19
22
  "\n" +
20
23
  "Android profile:\n" +
21
24
  " --profile android performs static, read-only Android project detection, manifest parsing,\n" +
22
- " permission/exported-component/intent-filter/deep-link audits, and static Gradle metadata\n" +
23
- " extraction. Gradle is never executed by default.\n" +
25
+ " permission/exported-component/intent-filter/deep-link audits, static Gradle metadata\n" +
26
+ " extraction, and (as of v0.4.1 Batch 8) eleven internal advanced security checks (network\n" +
27
+ " security config, backup/release configuration, hardcoded secrets, signing configuration,\n" +
28
+ " WebView, FileProvider, sensitive storage/logging, clipboard, and Firebase/Google services).\n" +
29
+ " Gradle and external tools are never executed by default.\n" +
24
30
  " --android-gradle-operations explicitly opts into running ONLY the listed allowlisted Gradle\n" +
25
31
  " operations (wrapper-version, tasks, assemble-debug, unit-test-debug, lint-debug) via the\n" +
26
32
  " project's own Gradle wrapper. Arbitrary Gradle tasks cannot be passed. This option is only\n" +
27
33
  " valid together with --profile android.\n" +
34
+ " --android-external-tools explicitly opts into running ONLY the listed allowlisted optional\n" +
35
+ " external security tools (semgrep, osv, android-lint, dependency-check). No arbitrary tool\n" +
36
+ " names, commands, or arguments can be passed. This option is only valid together with\n" +
37
+ " --profile android.\n" +
38
+ " --android-external-network controls whether a requested tool may use network access.\n" +
39
+ " Defaults to deny (osv is skipped unless supported offline data is available; semgrep,\n" +
40
+ " android-lint, and dependency-check always run offline/no-update regardless of this flag).\n" +
41
+ " allow-requested authorizes network only for an explicitly requested tool whose Batch 7\n" +
42
+ " contract supports it (currently only osv). This option is only valid together with\n" +
43
+ " --profile android.\n" +
28
44
  " Example: npm run security:validate -- --target \"<android-project-path>\" --profile android\n" +
29
- " Example: npm run security:validate -- --target \"<android-project-path>\" --profile android --android-gradle-operations wrapper-version,tasks";
45
+ " Example: npm run security:validate -- --target \"<android-project-path>\" --profile android --android-gradle-operations wrapper-version,tasks\n" +
46
+ " Example: npm run security:validate -- --target \"<android-project-path>\" --profile android --android-external-tools semgrep,android-lint\n" +
47
+ " Example: npm run security:validate -- --target \"<android-project-path>\" --profile android --android-external-tools osv --android-external-network allow-requested";
30
48
  // Parse CLI arguments from process.argv (after the node/tsx and script path).
31
49
  const rawArgs = process.argv.slice(2);
32
50
  const toolRoot = resolveToolRoot(import.meta.url);
@@ -99,13 +117,27 @@ if (config.profile === "android") {
99
117
  else {
100
118
  console.log(`Gradle ops : (none requested — static-only validation, zero Gradle process execution)`);
101
119
  }
120
+ // v0.4.1 Batch 8 — external tools remain explicit opt-in, mirroring Gradle
121
+ // operations exactly. "allow-requested" (the CLI-facing value) maps to the
122
+ // Batch 7 dispatcher's "allow-for-requested-tool" network policy value.
123
+ const externalNetworkPolicy = config.androidExternalNetworkPolicy === "allow-requested" ? "allow-for-requested-tool" : "deny";
124
+ if (config.androidExternalToolIds.length > 0) {
125
+ console.log(`External : ${config.androidExternalToolIds.join(", ")} (explicitly requested — network policy: ${config.androidExternalNetworkPolicy})`);
126
+ }
127
+ else {
128
+ console.log(`External : (none requested — zero external-tool process execution)`);
129
+ }
102
130
  console.log("");
131
+ const reportsDir = config.out;
103
132
  let result;
104
133
  try {
105
134
  result = await validateAndroidTarget({
106
135
  toolRoot,
107
136
  targetPath: args.target,
108
137
  requestedGradleOperationIds: config.androidGradleOperationIds,
138
+ requestedExternalToolIds: config.androidExternalToolIds,
139
+ externalNetworkPolicy: externalNetworkPolicy,
140
+ externalToolArtifactRoot: path.join(reportsDir, "external-tools"),
109
141
  });
110
142
  }
111
143
  catch (err) {
@@ -117,9 +149,10 @@ if (config.profile === "android") {
117
149
  const reportModel = toAndroidReportModel(result, {
118
150
  profile: config.profile,
119
151
  requestedGradleOperations: config.androidGradleOperationIds,
152
+ requestedExternalTools: config.androidExternalToolIds,
153
+ externalNetworkPolicy: config.androidExternalNetworkPolicy,
120
154
  });
121
155
  const textReport = renderAndroidTextReport(reportModel);
122
- const reportsDir = config.out;
123
156
  const prefix = args.reportPrefix ??
124
157
  reportFilenamePrefix({
125
158
  isSelf: result.target.local.isSelf,
@@ -8,10 +8,19 @@ const FLAGS_WITH_VALUE = {
8
8
  "--fail-on": "failOn",
9
9
  "--out": "out",
10
10
  };
11
+ // v0.4.2 Batch 3 -- presence-only flags (no following value consumed).
12
+ const BOOLEAN_FLAGS = {
13
+ "--android": "android",
14
+ };
11
15
  export function parseAuditArgs(argv) {
12
16
  const result = {};
13
17
  for (let i = 0; i < argv.length; i++) {
14
18
  const arg = argv[i];
19
+ const booleanKey = BOOLEAN_FLAGS[arg];
20
+ if (booleanKey) {
21
+ result[booleanKey] = true;
22
+ continue;
23
+ }
15
24
  const key = FLAGS_WITH_VALUE[arg];
16
25
  if (!key)
17
26
  continue;
@@ -28,6 +37,10 @@ export function normalizeAuditConfig(raw, toolRoot) {
28
37
  const formats = parseFormatOption(raw.format);
29
38
  const failOn = parseFailOnOption(raw.failOn);
30
39
  const out = raw.out !== undefined ? resolveOutDir(raw.out) : defaultOutDir(toolRoot, types.value);
40
+ const android = raw.android === true;
41
+ if (android && !types.value.includes("security")) {
42
+ throw new Error(`Invalid combination: --android requires --types to include "security" (e.g. --types security or --types code-rot,security).`);
43
+ }
31
44
  return {
32
45
  targetPathArg: raw.target,
33
46
  targetMode: raw.target === undefined ? "self" : "external",
@@ -46,7 +59,9 @@ export function normalizeAuditConfig(raw, toolRoot) {
46
59
  raw.include === undefined &&
47
60
  raw.format === undefined &&
48
61
  raw.failOn === undefined &&
49
- raw.out === undefined,
62
+ raw.out === undefined &&
63
+ raw.android === undefined,
64
+ android,
50
65
  };
51
66
  }
52
67
  function splitAndNormalizeList(raw, flagName) {
@@ -6,7 +6,7 @@ import { collectSourceOfTruth } from "./sourceOfTruth.js";
6
6
  import { collectSourceFacts } from "./collectSourceFacts.js";
7
7
  import { collectPythonProjectMetadata } from "./pythonProjectMetadata.js";
8
8
  import { runSecurityAuditAdapter } from "../security/securityAuditAdapter.js";
9
- import { SECURITY_AUDIT_NOT_RUN_SUMMARY } from "../security/securityAuditTypes.js";
9
+ import { ANDROID_AUDIT_NOT_REQUESTED_SUMMARY, SECURITY_AUDIT_NOT_RUN_SUMMARY, } from "../security/securityAuditTypes.js";
10
10
  export async function runAudit(options) {
11
11
  const { config, toolRoot } = options;
12
12
  const registry = options.registry ?? DEFAULT_AUDIT_REGISTRY;
@@ -49,10 +49,12 @@ export async function runAudit(options) {
49
49
  // code-rot detector issues (registry order) first, then security findings
50
50
  // (security-validation check-execution order).
51
51
  let securitySummary = SECURITY_AUDIT_NOT_RUN_SUMMARY;
52
+ let androidSummary = ANDROID_AUDIT_NOT_REQUESTED_SUMMARY;
52
53
  if (config.types.includes("security")) {
53
- const securityAudit = await runSecurityAuditAdapter({ toolRoot, config });
54
+ const securityAudit = await runSecurityAuditAdapter({ toolRoot, config, android: config.android ? { enabled: true } : undefined }, options.securityDependencies);
54
55
  issues.push(...securityAudit.issues);
55
56
  securitySummary = securityAudit.summary;
57
+ androidSummary = securityAudit.android;
56
58
  }
57
59
  const issueCounts = countIssuesBySeverity(issues);
58
60
  const { exitCode, reason } = calculateAuditExitCode(issues, config.failOn);
@@ -64,6 +66,7 @@ export async function runAudit(options) {
64
66
  failOn: config.failOn,
65
67
  out: config.out,
66
68
  isDefaultRun: config.isDefaultRun,
69
+ android: config.android,
67
70
  },
68
71
  targetSummary: {
69
72
  rootPath: target.rootPath,
@@ -81,6 +84,7 @@ export async function runAudit(options) {
81
84
  sourceFacts,
82
85
  pythonProjectMetadata,
83
86
  securitySummary,
87
+ androidSummary,
84
88
  noDetectorsRegistered: selected.length === 0,
85
89
  };
86
90
  }
@@ -166,6 +166,7 @@ export function buildAuditReportModel(result, opts) {
166
166
  failOn: result.configSummary.failOn,
167
167
  out: result.configSummary.out,
168
168
  isDefaultRun: result.configSummary.isDefaultRun,
169
+ android: result.configSummary.android,
169
170
  },
170
171
  summary: {
171
172
  totalIssues: issues.length,
@@ -191,6 +192,10 @@ export function buildAuditReportModel(result, opts) {
191
192
  sourceFacts: summarizeSourceFacts(result.sourceFacts),
192
193
  pythonProjectMetadata: result.pythonProjectMetadata,
193
194
  securitySummary: result.securitySummary,
195
+ androidSecurity: {
196
+ summary: result.androidSummary,
197
+ candidates: result.androidSummary.candidateSummary,
198
+ },
194
199
  detectors,
195
200
  issues,
196
201
  skippedDetectors: result.skippedDetectors,
@@ -252,5 +257,7 @@ function reconstructCommand(result) {
252
257
  parts.push("--format", cfg.formats.join(","));
253
258
  parts.push("--fail-on", cfg.failOn);
254
259
  parts.push("--out", cfg.out);
260
+ if (cfg.android)
261
+ parts.push("--android");
255
262
  return parts.join(" ");
256
263
  }
@@ -21,6 +21,7 @@ export function renderAuditJsonReport(model) {
21
21
  sourceFacts: model.sourceFacts,
22
22
  pythonProjectMetadata: model.pythonProjectMetadata,
23
23
  securitySummary: model.securitySummary,
24
+ androidSecurity: model.androidSecurity,
24
25
  detectors: model.detectors,
25
26
  issues: model.issues,
26
27
  skippedDetectors: model.skippedDetectors,