@shepai/cli 1.175.0 → 1.175.1-pr527.ea242b8

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 (416) hide show
  1. package/apis/json-schema/ActionDispositionEntry.yaml +14 -0
  2. package/apis/json-schema/DependencyFinding.yaml +28 -0
  3. package/apis/json-schema/DependencyRiskType.yaml +11 -0
  4. package/apis/json-schema/DependencyRules.yaml +38 -0
  5. package/apis/json-schema/EffectivePolicySnapshot.yaml +24 -0
  6. package/apis/json-schema/FeatureFlags.yaml +5 -0
  7. package/apis/json-schema/ReleaseIntegrityCheck.yaml +22 -0
  8. package/apis/json-schema/ReleaseIntegrityCheckType.yaml +9 -0
  9. package/apis/json-schema/ReleaseIntegrityResult.yaml +16 -0
  10. package/apis/json-schema/ReleaseRules.yaml +21 -0
  11. package/apis/json-schema/SecurityActionCategory.yaml +10 -0
  12. package/apis/json-schema/SecurityActionDisposition.yaml +8 -0
  13. package/apis/json-schema/SecurityConfig.yaml +17 -0
  14. package/apis/json-schema/SecurityEvent.yaml +36 -0
  15. package/apis/json-schema/SecurityMode.yaml +8 -0
  16. package/apis/json-schema/SecurityPolicy.yaml +24 -0
  17. package/apis/json-schema/SecuritySeverity.yaml +9 -0
  18. package/apis/json-schema/Settings.yaml +3 -0
  19. package/dist/packages/core/src/application/ports/output/agents/agent-executor.interface.d.ts +15 -1
  20. package/dist/packages/core/src/application/ports/output/agents/agent-executor.interface.d.ts.map +1 -1
  21. package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts +3 -1
  22. package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts.map +1 -1
  23. package/dist/packages/core/src/application/ports/output/repositories/security-event.repository.interface.d.ts +76 -0
  24. package/dist/packages/core/src/application/ports/output/repositories/security-event.repository.interface.d.ts.map +1 -0
  25. package/dist/packages/core/src/application/ports/output/repositories/security-event.repository.interface.js +11 -0
  26. package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.d.ts +38 -0
  27. package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.d.ts.map +1 -1
  28. package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.js +9 -0
  29. package/dist/packages/core/src/application/ports/output/services/security-policy-service.interface.d.ts +77 -0
  30. package/dist/packages/core/src/application/ports/output/services/security-policy-service.interface.d.ts.map +1 -0
  31. package/dist/packages/core/src/application/ports/output/services/security-policy-service.interface.js +13 -0
  32. package/dist/packages/core/src/application/ports/output/services/spec-initializer.interface.d.ts +11 -0
  33. package/dist/packages/core/src/application/ports/output/services/spec-initializer.interface.d.ts.map +1 -1
  34. package/dist/packages/core/src/application/use-cases/agents/approve-agent-run.use-case.d.ts.map +1 -1
  35. package/dist/packages/core/src/application/use-cases/agents/approve-agent-run.use-case.js +2 -0
  36. package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.d.ts.map +1 -1
  37. package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.js +2 -0
  38. package/dist/packages/core/src/application/use-cases/features/check-and-unblock-features.use-case.d.ts.map +1 -1
  39. package/dist/packages/core/src/application/use-cases/features/check-and-unblock-features.use-case.js +2 -0
  40. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
  41. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +1 -0
  42. package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.d.ts.map +1 -1
  43. package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.js +2 -0
  44. package/dist/packages/core/src/application/use-cases/features/start-feature.use-case.d.ts.map +1 -1
  45. package/dist/packages/core/src/application/use-cases/features/start-feature.use-case.js +2 -0
  46. package/dist/packages/core/src/application/use-cases/security/enforce-security.use-case.d.ts +71 -0
  47. package/dist/packages/core/src/application/use-cases/security/enforce-security.use-case.d.ts.map +1 -0
  48. package/dist/packages/core/src/application/use-cases/security/enforce-security.use-case.js +215 -0
  49. package/dist/packages/core/src/application/use-cases/security/evaluate-security-policy.use-case.d.ts +24 -0
  50. package/dist/packages/core/src/application/use-cases/security/evaluate-security-policy.use-case.d.ts.map +1 -0
  51. package/dist/packages/core/src/application/use-cases/security/evaluate-security-policy.use-case.js +56 -0
  52. package/dist/packages/core/src/application/use-cases/security/get-security-state.use-case.d.ts +36 -0
  53. package/dist/packages/core/src/application/use-cases/security/get-security-state.use-case.d.ts.map +1 -0
  54. package/dist/packages/core/src/application/use-cases/security/get-security-state.use-case.js +76 -0
  55. package/dist/packages/core/src/application/use-cases/security/record-security-event.use-case.d.ts +14 -0
  56. package/dist/packages/core/src/application/use-cases/security/record-security-event.use-case.d.ts.map +1 -0
  57. package/dist/packages/core/src/application/use-cases/security/record-security-event.use-case.js +46 -0
  58. package/dist/packages/core/src/domain/errors/security-violation.error.d.ts +15 -0
  59. package/dist/packages/core/src/domain/errors/security-violation.error.d.ts.map +1 -0
  60. package/dist/packages/core/src/domain/errors/security-violation.error.js +20 -0
  61. package/dist/packages/core/src/domain/factories/settings-defaults.factory.d.ts.map +1 -1
  62. package/dist/packages/core/src/domain/factories/settings-defaults.factory.js +6 -1
  63. package/dist/packages/core/src/domain/generated/output.d.ts +263 -0
  64. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  65. package/dist/packages/core/src/domain/generated/output.js +43 -0
  66. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  67. package/dist/packages/core/src/infrastructure/di/container.js +57 -0
  68. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/security-event.mapper.d.ts +44 -0
  69. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/security-event.mapper.d.ts.map +1 -0
  70. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/security-event.mapper.js +55 -0
  71. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +4 -0
  72. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
  73. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +17 -0
  74. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/053-add-security-settings-columns.d.ts +18 -0
  75. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/053-add-security-settings-columns.d.ts.map +1 -0
  76. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/053-add-security-settings-columns.js +31 -0
  77. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/054-create-security-events-table.d.ts +29 -0
  78. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/054-create-security-events-table.d.ts.map +1 -0
  79. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/054-create-security-events-table.js +53 -0
  80. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/056-add-feature-flag-supply-chain-security.d.ts +16 -0
  81. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/056-add-feature-flag-supply-chain-security.d.ts.map +1 -0
  82. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/056-add-feature-flag-supply-chain-security.js +22 -0
  83. package/dist/packages/core/src/infrastructure/repositories/sqlite-security-event.repository.d.ts +24 -0
  84. package/dist/packages/core/src/infrastructure/repositories/sqlite-security-event.repository.d.ts.map +1 -0
  85. package/dist/packages/core/src/infrastructure/repositories/sqlite-security-event.repository.js +96 -0
  86. package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.d.ts.map +1 -1
  87. package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.js +15 -3
  88. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts +2 -0
  89. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts.map +1 -1
  90. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.js +12 -0
  91. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-interactive-executor.service.d.ts.map +1 -1
  92. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-interactive-executor.service.js +44 -4
  93. package/dist/packages/core/src/infrastructure/services/agents/common/executors/security-constraint-validator.d.ts +22 -0
  94. package/dist/packages/core/src/infrastructure/services/agents/common/executors/security-constraint-validator.d.ts.map +1 -0
  95. package/dist/packages/core/src/infrastructure/services/agents/common/executors/security-constraint-validator.js +30 -0
  96. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.d.ts +10 -0
  97. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.d.ts.map +1 -1
  98. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts +35 -1
  99. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts.map +1 -1
  100. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts +3 -1
  101. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts.map +1 -1
  102. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js +7 -1
  103. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts +3 -1
  104. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
  105. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +32 -1
  106. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
  107. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +25 -0
  108. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/security-pre-check.d.ts +59 -0
  109. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/security-pre-check.d.ts.map +1 -0
  110. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/security-pre-check.js +89 -0
  111. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts +4 -1
  112. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts.map +1 -1
  113. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.js +10 -0
  114. package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts +10 -1
  115. package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts.map +1 -1
  116. package/dist/packages/core/src/infrastructure/services/external/github-repository.service.js +101 -1
  117. package/dist/packages/core/src/infrastructure/services/security/dependency-risk-evaluator.d.ts +53 -0
  118. package/dist/packages/core/src/infrastructure/services/security/dependency-risk-evaluator.d.ts.map +1 -0
  119. package/dist/packages/core/src/infrastructure/services/security/dependency-risk-evaluator.js +241 -0
  120. package/dist/packages/core/src/infrastructure/services/security/release-integrity-evaluator.d.ts +44 -0
  121. package/dist/packages/core/src/infrastructure/services/security/release-integrity-evaluator.d.ts.map +1 -0
  122. package/dist/packages/core/src/infrastructure/services/security/release-integrity-evaluator.js +194 -0
  123. package/dist/packages/core/src/infrastructure/services/security/security-policy-file-reader.d.ts +28 -0
  124. package/dist/packages/core/src/infrastructure/services/security/security-policy-file-reader.d.ts.map +1 -0
  125. package/dist/packages/core/src/infrastructure/services/security/security-policy-file-reader.js +50 -0
  126. package/dist/packages/core/src/infrastructure/services/security/security-policy-validator.d.ts +26 -0
  127. package/dist/packages/core/src/infrastructure/services/security/security-policy-validator.d.ts.map +1 -0
  128. package/dist/packages/core/src/infrastructure/services/security/security-policy-validator.js +147 -0
  129. package/dist/packages/core/src/infrastructure/services/security/security-policy.service.d.ts +44 -0
  130. package/dist/packages/core/src/infrastructure/services/security/security-policy.service.d.ts.map +1 -0
  131. package/dist/packages/core/src/infrastructure/services/security/security-policy.service.js +174 -0
  132. package/dist/packages/core/src/infrastructure/services/spec/spec-initializer.service.d.ts +1 -0
  133. package/dist/packages/core/src/infrastructure/services/spec/spec-initializer.service.d.ts.map +1 -1
  134. package/dist/packages/core/src/infrastructure/services/spec/spec-initializer.service.js +61 -0
  135. package/dist/src/presentation/cli/commands/security.command.d.ts +16 -0
  136. package/dist/src/presentation/cli/commands/security.command.d.ts.map +1 -0
  137. package/dist/src/presentation/cli/commands/security.command.js +133 -0
  138. package/dist/src/presentation/cli/index.js +2 -0
  139. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts.map +1 -1
  140. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.js +5 -1
  141. package/dist/src/presentation/web/app/actions/security.d.ts +28 -0
  142. package/dist/src/presentation/web/app/actions/security.d.ts.map +1 -0
  143. package/dist/src/presentation/web/app/actions/security.js +59 -0
  144. package/dist/src/presentation/web/app/build-graph-nodes.d.ts +3 -1
  145. package/dist/src/presentation/web/app/build-graph-nodes.d.ts.map +1 -1
  146. package/dist/src/presentation/web/app/build-graph-nodes.js +2 -0
  147. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +3 -1
  148. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
  149. package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
  150. package/dist/src/presentation/web/components/common/feature-node/feature-node.js +2 -1
  151. package/dist/src/presentation/web/components/common/repository-node/repository-drawer.d.ts +3 -1
  152. package/dist/src/presentation/web/components/common/repository-node/repository-drawer.d.ts.map +1 -1
  153. package/dist/src/presentation/web/components/common/repository-node/repository-drawer.js +3 -2
  154. package/dist/src/presentation/web/components/common/repository-node/security-panel.d.ts +6 -0
  155. package/dist/src/presentation/web/components/common/repository-node/security-panel.d.ts.map +1 -0
  156. package/dist/src/presentation/web/components/common/repository-node/security-panel.js +29 -0
  157. package/dist/src/presentation/web/components/common/repository-node/security-panel.stories.d.ts +10 -0
  158. package/dist/src/presentation/web/components/common/repository-node/security-panel.stories.d.ts.map +1 -0
  159. package/dist/src/presentation/web/components/common/repository-node/security-panel.stories.js +53 -0
  160. package/dist/src/presentation/web/components/common/security-badge.d.ts +7 -0
  161. package/dist/src/presentation/web/components/common/security-badge.d.ts.map +1 -0
  162. package/dist/src/presentation/web/components/common/security-badge.js +30 -0
  163. package/dist/src/presentation/web/components/common/security-badge.stories.d.ts +12 -0
  164. package/dist/src/presentation/web/components/common/security-badge.stories.d.ts.map +1 -0
  165. package/dist/src/presentation/web/components/common/security-badge.stories.js +20 -0
  166. package/dist/src/presentation/web/components/features/settings/feature-flags-settings-section.d.ts.map +1 -1
  167. package/dist/src/presentation/web/components/features/settings/feature-flags-settings-section.js +3 -0
  168. package/dist/src/presentation/web/components/features/settings/feature-flags-settings-section.stories.d.ts.map +1 -1
  169. package/dist/src/presentation/web/components/features/settings/feature-flags-settings-section.stories.js +3 -0
  170. package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts.map +1 -1
  171. package/dist/src/presentation/web/components/features/settings/settings-page-client.js +26 -7
  172. package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.d.ts.map +1 -1
  173. package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.js +1 -0
  174. package/dist/src/presentation/web/components/features/settings/supply-chain-security-settings-section.d.ts +6 -0
  175. package/dist/src/presentation/web/components/features/settings/supply-chain-security-settings-section.d.ts.map +1 -0
  176. package/dist/src/presentation/web/components/features/settings/supply-chain-security-settings-section.js +60 -0
  177. package/dist/src/presentation/web/components/features/settings/supply-chain-security-settings-section.stories.d.ts +14 -0
  178. package/dist/src/presentation/web/components/features/settings/supply-chain-security-settings-section.stories.d.ts.map +1 -0
  179. package/dist/src/presentation/web/components/features/settings/supply-chain-security-settings-section.stories.js +116 -0
  180. package/dist/translations/ar/cli.json +21 -0
  181. package/dist/translations/ar/web.json +43 -1
  182. package/dist/translations/de/cli.json +21 -0
  183. package/dist/translations/de/web.json +43 -1
  184. package/dist/translations/en/cli.json +21 -0
  185. package/dist/translations/en/web.json +43 -1
  186. package/dist/translations/es/cli.json +21 -0
  187. package/dist/translations/es/web.json +43 -1
  188. package/dist/translations/fr/cli.json +21 -0
  189. package/dist/translations/fr/web.json +43 -1
  190. package/dist/translations/he/cli.json +21 -0
  191. package/dist/translations/he/web.json +43 -1
  192. package/dist/translations/pt/cli.json +22 -1
  193. package/dist/translations/pt/web.json +43 -1
  194. package/dist/translations/ru/cli.json +21 -0
  195. package/dist/translations/ru/web.json +43 -1
  196. package/dist/tsconfig.build.tsbuildinfo +1 -1
  197. package/package.json +1 -1
  198. package/web/.next/BUILD_ID +1 -1
  199. package/web/.next/build-manifest.json +2 -2
  200. package/web/.next/fallback-build-manifest.json +2 -2
  201. package/web/.next/prerender-manifest.json +3 -3
  202. package/web/.next/required-server-files.js +3 -3
  203. package/web/.next/required-server-files.json +3 -3
  204. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +29 -29
  205. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  206. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  207. package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +27 -27
  208. package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
  209. package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
  210. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +30 -30
  211. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  212. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  213. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +38 -38
  214. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  215. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  216. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +38 -38
  217. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  218. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  219. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  220. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  221. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  222. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  223. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  224. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  225. package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +27 -27
  226. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
  227. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  228. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +30 -30
  229. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  230. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  231. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +38 -38
  232. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  233. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  234. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +38 -38
  235. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  236. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  237. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +27 -27
  238. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  239. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  240. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  241. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  242. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  243. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  244. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  245. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  246. package/web/.next/server/app/_global-error.html +2 -2
  247. package/web/.next/server/app/_global-error.rsc +1 -1
  248. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  249. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  250. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  251. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  252. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  253. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +6 -6
  254. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  255. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  256. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  257. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  258. package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
  259. package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
  260. package/web/.next/server/app/api/sessions/route.js.nft.json +1 -1
  261. package/web/.next/server/app/api/sessions-batch/route.js.nft.json +1 -1
  262. package/web/.next/server/app/features/page/server-reference-manifest.json +6 -6
  263. package/web/.next/server/app/features/page.js.nft.json +1 -1
  264. package/web/.next/server/app/features/page_client-reference-manifest.js +1 -1
  265. package/web/.next/server/app/settings/page/server-reference-manifest.json +33 -18
  266. package/web/.next/server/app/settings/page.js +1 -1
  267. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  268. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  269. package/web/.next/server/app/skills/page/server-reference-manifest.json +13 -13
  270. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  271. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  272. package/web/.next/server/app/tools/page/server-reference-manifest.json +11 -11
  273. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  274. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  275. package/web/.next/server/app/version/page/server-reference-manifest.json +6 -6
  276. package/web/.next/server/app/version/page.js.nft.json +1 -1
  277. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  278. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
  279. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
  280. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  281. package/web/.next/server/chunks/[root-of-the-server]__c78383b1._.js +1 -1
  282. package/web/.next/server/chunks/[root-of-the-server]__c78383b1._.js.map +1 -1
  283. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +1 -1
  284. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
  285. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_ad0071c9.js +1 -1
  286. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_ad0071c9.js.map +1 -1
  287. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_90d98b2b.js +1 -1
  288. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_90d98b2b.js.map +1 -1
  289. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_d3828105.js +1 -1
  290. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_d3828105.js.map +1 -1
  291. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  292. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  293. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
  294. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
  295. package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js +1 -1
  296. package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js.map +1 -1
  297. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  298. package/web/.next/server/chunks/ssr/[root-of-the-server]__51ec77a8._.js +1 -1
  299. package/web/.next/server/chunks/ssr/[root-of-the-server]__51ec77a8._.js.map +1 -1
  300. package/web/.next/server/chunks/ssr/[root-of-the-server]__540c615f._.js +2 -2
  301. package/web/.next/server/chunks/ssr/[root-of-the-server]__540c615f._.js.map +1 -1
  302. package/web/.next/server/chunks/ssr/[root-of-the-server]__66047a1b._.js +1 -1
  303. package/web/.next/server/chunks/ssr/[root-of-the-server]__66047a1b._.js.map +1 -1
  304. package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js +1 -1
  305. package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js.map +1 -1
  306. package/web/.next/server/chunks/ssr/[root-of-the-server]__a2d6c0ac._.js +4 -0
  307. package/web/.next/server/chunks/ssr/[root-of-the-server]__a2d6c0ac._.js.map +1 -0
  308. package/web/.next/server/chunks/ssr/[root-of-the-server]__a932cd3a._.js +1 -1
  309. package/web/.next/server/chunks/ssr/[root-of-the-server]__a932cd3a._.js.map +1 -1
  310. package/web/.next/server/chunks/ssr/[root-of-the-server]__aa72e794._.js +1 -1
  311. package/web/.next/server/chunks/ssr/[root-of-the-server]__aa72e794._.js.map +1 -1
  312. package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js +1 -1
  313. package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js.map +1 -1
  314. package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
  315. package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
  316. package/web/.next/server/chunks/ssr/_08eaf4b1._.js +3 -0
  317. package/web/.next/server/chunks/ssr/_08eaf4b1._.js.map +1 -0
  318. package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
  319. package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
  320. package/web/.next/server/chunks/ssr/_295fffde._.js +1 -1
  321. package/web/.next/server/chunks/ssr/_295fffde._.js.map +1 -1
  322. package/web/.next/server/chunks/ssr/_45496654._.js +1 -1
  323. package/web/.next/server/chunks/ssr/_45496654._.js.map +1 -1
  324. package/web/.next/server/chunks/ssr/_4cbb7f95._.js +1 -1
  325. package/web/.next/server/chunks/ssr/_4cbb7f95._.js.map +1 -1
  326. package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
  327. package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
  328. package/web/.next/server/chunks/ssr/_6abfa39e._.js +1 -1
  329. package/web/.next/server/chunks/ssr/_783debcb._.js +9 -0
  330. package/web/.next/server/chunks/ssr/_783debcb._.js.map +1 -0
  331. package/web/.next/server/chunks/ssr/{_af6b8b94._.js → _e7f76333._.js} +2 -2
  332. package/web/.next/server/chunks/ssr/{_af6b8b94._.js.map → _e7f76333._.js.map} +1 -1
  333. package/web/.next/server/chunks/ssr/_f8c55130._.js +1 -1
  334. package/web/.next/server/chunks/ssr/_f8c55130._.js.map +1 -1
  335. package/web/.next/server/chunks/ssr/{_e0dd6fcf._.js → _fc1578d7._.js} +2 -2
  336. package/web/.next/server/chunks/ssr/_fc1578d7._.js.map +1 -0
  337. package/web/.next/server/chunks/ssr/_ff04802c._.js +3 -0
  338. package/web/.next/server/chunks/ssr/_ff04802c._.js.map +1 -0
  339. package/web/.next/server/chunks/ssr/_ff87ffa6._.js +3 -0
  340. package/web/.next/server/chunks/ssr/_ff87ffa6._.js.map +1 -0
  341. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  342. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  343. package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js +1 -1
  344. package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js.map +1 -1
  345. package/web/.next/server/chunks/ssr/src_presentation_web_17d39233._.js +1 -1
  346. package/web/.next/server/chunks/ssr/src_presentation_web_17d39233._.js.map +1 -1
  347. package/web/.next/server/chunks/ssr/src_presentation_web_54b02639._.js +2 -2
  348. package/web/.next/server/chunks/ssr/src_presentation_web_54b02639._.js.map +1 -1
  349. package/web/.next/server/chunks/ssr/src_presentation_web_7b7b9e3b._.js +2 -2
  350. package/web/.next/server/chunks/ssr/src_presentation_web_7b7b9e3b._.js.map +1 -1
  351. package/web/.next/server/chunks/ssr/src_presentation_web_807cba76._.js +1 -1
  352. package/web/.next/server/chunks/ssr/src_presentation_web_807cba76._.js.map +1 -1
  353. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_90b5e66e.js +1 -1
  354. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_90b5e66e.js.map +1 -1
  355. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_4ce30db7.js +1 -1
  356. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_4ce30db7.js.map +1 -1
  357. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_e4032193.js +1 -1
  358. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_e4032193.js.map +1 -1
  359. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  360. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
  361. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -1
  362. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js +1 -1
  363. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js.map +1 -1
  364. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  365. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  366. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js +1 -1
  367. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js.map +1 -1
  368. package/web/.next/server/chunks/ssr/src_presentation_web_db9fa0c2._.js +1 -1
  369. package/web/.next/server/chunks/ssr/src_presentation_web_db9fa0c2._.js.map +1 -1
  370. package/web/.next/server/chunks/ssr/src_presentation_web_e1cd1869._.js +1 -1
  371. package/web/.next/server/chunks/ssr/src_presentation_web_e1cd1869._.js.map +1 -1
  372. package/web/.next/server/chunks/ssr/src_presentation_web_e3a30e30._.js +1 -1
  373. package/web/.next/server/chunks/ssr/src_presentation_web_e3a30e30._.js.map +1 -1
  374. package/web/.next/server/chunks/ssr/translations_23dd5e7e._.js +1 -1
  375. package/web/.next/server/chunks/ssr/translations_23dd5e7e._.js.map +1 -1
  376. package/web/.next/server/pages/500.html +2 -2
  377. package/web/.next/server/server-reference-manifest.js +1 -1
  378. package/web/.next/server/server-reference-manifest.json +74 -59
  379. package/web/.next/static/chunks/{238fdbed09dc61b6.js → 1eeabda286169861.js} +2 -2
  380. package/web/.next/static/chunks/20ec94c610d07a10.css +1 -0
  381. package/web/.next/static/chunks/{940c842293a6ee9b.js → 2dcae7bd1f3e2b51.js} +1 -1
  382. package/web/.next/static/chunks/3aba9d2242420cb5.js +1 -0
  383. package/web/.next/static/chunks/6003ad985fb78e62.js +1 -0
  384. package/web/.next/static/chunks/{0b07ee72b0c639ef.js → 69aa6a996dccb7dc.js} +2 -2
  385. package/web/.next/static/chunks/{873e837cd1179cdd.js → 6e5aeb5da5bb2ab6.js} +1 -1
  386. package/web/.next/static/chunks/{2ad924f5ba5ec0a6.js → 7c8e1ab108e3ceea.js} +1 -1
  387. package/web/.next/static/chunks/{bc41a393614b1192.js → 825ddcb7c361b2fe.js} +1 -1
  388. package/web/.next/static/chunks/{a22ee308ae1509ca.js → 89a6182ae40ac10b.js} +1 -1
  389. package/web/.next/static/chunks/{d26542df5ecc8717.js → a6d516b7e128f889.js} +1 -1
  390. package/web/.next/static/chunks/ae81796726a9bba3.js +1 -0
  391. package/web/.next/static/chunks/{b49ab0b290e9342d.js → b46545caae3b4930.js} +1 -1
  392. package/web/.next/static/chunks/{b7b5d65a5dd2fff1.js → c43f00ac45c5381d.js} +1 -1
  393. package/web/.next/static/chunks/{39054eabee156e55.js → c741f40bcb2abe54.js} +3 -3
  394. package/web/.next/static/chunks/{1b336d1266a0aa3d.js → dfc05704351fc940.js} +1 -1
  395. package/web/.next/static/chunks/eb72ac7aa8986962.js +1 -0
  396. package/web/.next/static/chunks/eef5d47669e61a54.js +3 -0
  397. package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js +0 -4
  398. package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js.map +0 -1
  399. package/web/.next/server/chunks/ssr/_2b021b35._.js +0 -3
  400. package/web/.next/server/chunks/ssr/_2b021b35._.js.map +0 -1
  401. package/web/.next/server/chunks/ssr/_43ba79e7._.js +0 -3
  402. package/web/.next/server/chunks/ssr/_43ba79e7._.js.map +0 -1
  403. package/web/.next/server/chunks/ssr/_7cb0396e._.js +0 -3
  404. package/web/.next/server/chunks/ssr/_7cb0396e._.js.map +0 -1
  405. package/web/.next/server/chunks/ssr/_e0dd6fcf._.js.map +0 -1
  406. package/web/.next/server/chunks/ssr/_e680c57c._.js +0 -9
  407. package/web/.next/server/chunks/ssr/_e680c57c._.js.map +0 -1
  408. package/web/.next/static/chunks/28f6b1cab38ab025.js +0 -3
  409. package/web/.next/static/chunks/8b0a9cb5109fe899.js +0 -1
  410. package/web/.next/static/chunks/a20f2d6f76f469b7.css +0 -1
  411. package/web/.next/static/chunks/b2aa69e4b0b032d9.js +0 -1
  412. package/web/.next/static/chunks/b65e555419a0c664.js +0 -1
  413. package/web/.next/static/chunks/ba0e0fa2d1a650bb.js +0 -1
  414. /package/web/.next/static/{9rcv3ICw0kZNuv3TVdO8E → 4jtpgWCvk_Q6-K-puXRhW}/_buildManifest.js +0 -0
  415. /package/web/.next/static/{9rcv3ICw0kZNuv3TVdO8E → 4jtpgWCvk_Q6-K-puXRhW}/_clientMiddlewareManifest.json +0 -0
  416. /package/web/.next/static/{9rcv3ICw0kZNuv3TVdO8E → 4jtpgWCvk_Q6-K-puXRhW}/_ssgManifest.js +0 -0
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Release Integrity Evaluator
3
+ *
4
+ * Checks release pipeline integrity for a repository:
5
+ * - CI workflow exists and publishes from CI (not local)
6
+ * - NPM_TOKEN and RELEASE_TOKEN referenced as secrets (not hardcoded)
7
+ * - npm provenance flags (--provenance) present in publish steps
8
+ * - Release workflow integrity (semantic-release configured)
9
+ *
10
+ * Returns a ReleaseIntegrityResult with individual check results and overall pass/fail.
11
+ */
12
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
13
+ import { join } from 'node:path';
14
+ import { ReleaseIntegrityCheckType, SecuritySeverity } from '../../../domain/generated/output.js';
15
+ /**
16
+ * Token env var names that should use secrets.* references.
17
+ */
18
+ const TOKEN_ENV_NAMES = ['GITHUB_TOKEN', 'RELEASE_TOKEN', 'NPM_TOKEN', 'NODE_AUTH_TOKEN'];
19
+ /**
20
+ * Pattern for a secrets.* reference in a YAML value.
21
+ */
22
+ const SECRETS_REF_PATTERN = /\$\{\{\s*secrets\./;
23
+ /**
24
+ * Pattern for detecting npm publish commands.
25
+ */
26
+ const NPM_PUBLISH_PATTERN = /npm\s+publish/;
27
+ /**
28
+ * Pattern for detecting --provenance flag.
29
+ */
30
+ const PROVENANCE_FLAG_PATTERN = /--provenance/;
31
+ /**
32
+ * Pattern for detecting semantic-release.
33
+ */
34
+ const SEMANTIC_RELEASE_PATTERN = /semantic-release/;
35
+ export class ReleaseIntegrityEvaluator {
36
+ /**
37
+ * Evaluate release pipeline integrity.
38
+ *
39
+ * @param repositoryPath - Absolute path to the repository root
40
+ * @param rules - Release integrity policy rules
41
+ * @returns Aggregated result with individual check details
42
+ */
43
+ evaluate(repositoryPath, rules) {
44
+ const checks = [];
45
+ const workflowDir = join(repositoryPath, '.github', 'workflows');
46
+ // Read all workflow files
47
+ const workflowContents = this.readWorkflowFiles(workflowDir);
48
+ // Check CI-only publishing
49
+ if (rules.requireCiOnlyPublishing) {
50
+ checks.push(this.checkCiOnlyPublishing(workflowDir, workflowContents));
51
+ }
52
+ // Check secret configuration (no hardcoded tokens)
53
+ if (rules.requireCiOnlyPublishing) {
54
+ checks.push(this.checkSecretConfiguration(workflowContents));
55
+ }
56
+ // Check provenance configuration
57
+ if (rules.requireProvenance) {
58
+ checks.push(...this.checkProvenanceConfiguration(workflowContents));
59
+ }
60
+ // Check workflow integrity
61
+ if (rules.checkWorkflowIntegrity) {
62
+ checks.push(this.checkWorkflowIntegrity(workflowContents));
63
+ }
64
+ return {
65
+ checks,
66
+ passed: checks.length === 0 || checks.every((c) => c.passed),
67
+ };
68
+ }
69
+ /**
70
+ * Read all YAML workflow files from .github/workflows/.
71
+ */
72
+ readWorkflowFiles(workflowDir) {
73
+ if (!existsSync(workflowDir)) {
74
+ return [];
75
+ }
76
+ try {
77
+ const files = readdirSync(workflowDir).filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'));
78
+ return files.map((f) => readFileSync(join(workflowDir, f), 'utf-8'));
79
+ }
80
+ catch {
81
+ return [];
82
+ }
83
+ }
84
+ /**
85
+ * Check that CI workflow files exist (publishing happens in CI, not locally).
86
+ */
87
+ checkCiOnlyPublishing(workflowDir, workflowContents) {
88
+ if (workflowContents.length === 0) {
89
+ return {
90
+ checkType: ReleaseIntegrityCheckType.CiOnlyPublishing,
91
+ passed: false,
92
+ message: 'No CI workflow files found in .github/workflows/. Publishing must happen in CI, not locally.',
93
+ severity: SecuritySeverity.Critical,
94
+ };
95
+ }
96
+ return {
97
+ checkType: ReleaseIntegrityCheckType.CiOnlyPublishing,
98
+ passed: true,
99
+ message: 'CI workflow files found. Publishing is configured for CI execution.',
100
+ severity: SecuritySeverity.Critical,
101
+ };
102
+ }
103
+ /**
104
+ * Check that tokens are referenced as secrets, not hardcoded.
105
+ * Scans for known token env var names and verifies they use ${{ secrets.* }}.
106
+ */
107
+ checkSecretConfiguration(workflowContents) {
108
+ const allContent = workflowContents.join('\n');
109
+ const lines = allContent.split('\n');
110
+ for (const line of lines) {
111
+ const trimmed = line.trim();
112
+ for (const tokenName of TOKEN_ENV_NAMES) {
113
+ // Match lines like "NPM_TOKEN: value" or "NPM_TOKEN: 'value'"
114
+ const pattern = new RegExp(`^${tokenName}\\s*:\\s*(.+)$`);
115
+ const match = pattern.exec(trimmed);
116
+ if (match) {
117
+ const value = match[1].trim();
118
+ // Value must contain a secrets.* reference to be safe
119
+ if (!SECRETS_REF_PATTERN.test(value)) {
120
+ return {
121
+ checkType: ReleaseIntegrityCheckType.SecretConfiguration,
122
+ passed: false,
123
+ message: 'Hardcoded token detected in workflow files. Tokens must use ${{ secrets.* }} references.',
124
+ severity: SecuritySeverity.Critical,
125
+ };
126
+ }
127
+ }
128
+ }
129
+ }
130
+ return {
131
+ checkType: ReleaseIntegrityCheckType.SecretConfiguration,
132
+ passed: true,
133
+ message: 'Tokens are properly referenced using ${{ secrets.* }} expressions.',
134
+ severity: SecuritySeverity.Critical,
135
+ };
136
+ }
137
+ /**
138
+ * Check that npm publish commands include --provenance flag.
139
+ */
140
+ checkProvenanceConfiguration(workflowContents) {
141
+ const allContent = workflowContents.join('\n');
142
+ // If no npm publish commands found, provenance is not applicable
143
+ if (!NPM_PUBLISH_PATTERN.test(allContent)) {
144
+ return [];
145
+ }
146
+ // Check if all npm publish commands have --provenance
147
+ const lines = allContent.split('\n');
148
+ let hasPublishWithoutProvenance = false;
149
+ for (const line of lines) {
150
+ if (NPM_PUBLISH_PATTERN.test(line) && !PROVENANCE_FLAG_PATTERN.test(line)) {
151
+ hasPublishWithoutProvenance = true;
152
+ break;
153
+ }
154
+ }
155
+ if (hasPublishWithoutProvenance) {
156
+ return [
157
+ {
158
+ checkType: ReleaseIntegrityCheckType.ProvenanceConfiguration,
159
+ passed: false,
160
+ message: 'npm publish command found without --provenance flag. Add --provenance to generate SLSA provenance attestations.',
161
+ severity: SecuritySeverity.Medium,
162
+ },
163
+ ];
164
+ }
165
+ return [
166
+ {
167
+ checkType: ReleaseIntegrityCheckType.ProvenanceConfiguration,
168
+ passed: true,
169
+ message: 'npm publish commands include --provenance flag for SLSA provenance.',
170
+ severity: SecuritySeverity.Medium,
171
+ },
172
+ ];
173
+ }
174
+ /**
175
+ * Check workflow integrity (semantic-release is configured).
176
+ */
177
+ checkWorkflowIntegrity(workflowContents) {
178
+ const allContent = workflowContents.join('\n');
179
+ if (!SEMANTIC_RELEASE_PATTERN.test(allContent)) {
180
+ return {
181
+ checkType: ReleaseIntegrityCheckType.WorkflowIntegrity,
182
+ passed: false,
183
+ message: 'semantic-release not found in CI workflows. Automated release management is recommended.',
184
+ severity: SecuritySeverity.Medium,
185
+ };
186
+ }
187
+ return {
188
+ checkType: ReleaseIntegrityCheckType.WorkflowIntegrity,
189
+ passed: true,
190
+ message: 'semantic-release is configured in CI workflows.',
191
+ severity: SecuritySeverity.Medium,
192
+ };
193
+ }
194
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Security Policy File Reader
3
+ *
4
+ * Reads and parses shep.security.yaml from a repository root using js-yaml.
5
+ * Returns the parsed object or null if the file does not exist.
6
+ * Throws with actionable messages on YAML syntax errors.
7
+ *
8
+ * Uses DEFAULT_SCHEMA to prevent arbitrary code execution from YAML tags.
9
+ */
10
+ import type { SecurityPolicy } from '../../../domain/generated/output.js';
11
+ /**
12
+ * The filename for the security policy file at the repository root.
13
+ */
14
+ export declare const SECURITY_POLICY_FILENAME = "shep.security.yaml";
15
+ /**
16
+ * Reads and parses the security policy YAML file from a repository.
17
+ */
18
+ export declare class SecurityPolicyFileReader {
19
+ /**
20
+ * Read and parse the security policy file from the given repository path.
21
+ *
22
+ * @param repositoryPath - Absolute path to the repository root
23
+ * @returns Parsed policy object, or null if file does not exist or is empty
24
+ * @throws Error with actionable message if YAML is malformed
25
+ */
26
+ read(repositoryPath: string): Promise<Partial<SecurityPolicy> | null>;
27
+ }
28
+ //# sourceMappingURL=security-policy-file-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-policy-file-reader.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/security/security-policy-file-reader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAE1E;;GAEG;AACH,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAE7D;;GAEG;AACH,qBAAa,wBAAwB;IACnC;;;;;;OAMG;IACG,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;CA0B5E"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Security Policy File Reader
3
+ *
4
+ * Reads and parses shep.security.yaml from a repository root using js-yaml.
5
+ * Returns the parsed object or null if the file does not exist.
6
+ * Throws with actionable messages on YAML syntax errors.
7
+ *
8
+ * Uses DEFAULT_SCHEMA to prevent arbitrary code execution from YAML tags.
9
+ */
10
+ import { readFileSync, existsSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import yaml from 'js-yaml';
13
+ /**
14
+ * The filename for the security policy file at the repository root.
15
+ */
16
+ export const SECURITY_POLICY_FILENAME = 'shep.security.yaml';
17
+ /**
18
+ * Reads and parses the security policy YAML file from a repository.
19
+ */
20
+ export class SecurityPolicyFileReader {
21
+ /**
22
+ * Read and parse the security policy file from the given repository path.
23
+ *
24
+ * @param repositoryPath - Absolute path to the repository root
25
+ * @returns Parsed policy object, or null if file does not exist or is empty
26
+ * @throws Error with actionable message if YAML is malformed
27
+ */
28
+ async read(repositoryPath) {
29
+ const filePath = join(repositoryPath, SECURITY_POLICY_FILENAME);
30
+ if (!existsSync(filePath)) {
31
+ return null;
32
+ }
33
+ const content = readFileSync(filePath, 'utf-8');
34
+ try {
35
+ const parsed = yaml.load(content, {
36
+ schema: yaml.DEFAULT_SCHEMA,
37
+ filename: SECURITY_POLICY_FILENAME,
38
+ });
39
+ // Empty file or comment-only file yields null/undefined
40
+ if (parsed == null || typeof parsed !== 'object') {
41
+ return null;
42
+ }
43
+ return parsed;
44
+ }
45
+ catch (error) {
46
+ const message = error instanceof Error ? error.message : String(error);
47
+ throw new Error(`Failed to parse ${SECURITY_POLICY_FILENAME}: ${message}`);
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Security Policy Validator
3
+ *
4
+ * Validates a parsed security policy object against the expected schema.
5
+ * Checks required fields, valid enum values, contradictory rules,
6
+ * and reasonable input limits. Returns structured validation results
7
+ * with per-field error messages.
8
+ */
9
+ import type { PolicyValidationResult } from '../../../application/ports/output/services/security-policy-service.interface.js';
10
+ /**
11
+ * Validates parsed security policy objects against the expected schema.
12
+ */
13
+ export declare class SecurityPolicyValidator {
14
+ /**
15
+ * Validate a parsed policy object.
16
+ *
17
+ * @param policy - The parsed policy object (from YAML)
18
+ * @returns Validation result with errors array
19
+ */
20
+ validate(policy: Record<string, unknown>): PolicyValidationResult;
21
+ private validateActionDispositions;
22
+ private validateDependencyRules;
23
+ private validateReleaseRules;
24
+ private validateStringList;
25
+ }
26
+ //# sourceMappingURL=security-policy-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-policy-validator.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/security/security-policy-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iFAAiF,CAAC;AAY9H;;GAEG;AACH,qBAAa,uBAAuB;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,sBAAsB;IAiCjE,OAAO,CAAC,0BAA0B;IAwDlC,OAAO,CAAC,uBAAuB;IAgC/B,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,kBAAkB;CAgB3B"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Security Policy Validator
3
+ *
4
+ * Validates a parsed security policy object against the expected schema.
5
+ * Checks required fields, valid enum values, contradictory rules,
6
+ * and reasonable input limits. Returns structured validation results
7
+ * with per-field error messages.
8
+ */
9
+ import { SecurityMode, SecurityActionCategory, SecurityActionDisposition, } from '../../../domain/generated/output.js';
10
+ /** Maximum number of action disposition entries allowed */
11
+ const MAX_ACTION_DISPOSITIONS = 100;
12
+ /** Maximum number of entries in allowlist or denylist */
13
+ const MAX_LIST_ENTRIES = 100;
14
+ const VALID_MODES = Object.values(SecurityMode);
15
+ const VALID_CATEGORIES = Object.values(SecurityActionCategory);
16
+ const VALID_DISPOSITIONS = Object.values(SecurityActionDisposition);
17
+ /**
18
+ * Validates parsed security policy objects against the expected schema.
19
+ */
20
+ export class SecurityPolicyValidator {
21
+ /**
22
+ * Validate a parsed policy object.
23
+ *
24
+ * @param policy - The parsed policy object (from YAML)
25
+ * @returns Validation result with errors array
26
+ */
27
+ validate(policy) {
28
+ const errors = [];
29
+ // Validate mode (optional, but if present must be valid)
30
+ if (policy.mode !== undefined) {
31
+ if (!VALID_MODES.includes(policy.mode)) {
32
+ errors.push(`Invalid mode: "${String(policy.mode)}". Valid values: ${VALID_MODES.join(', ')}`);
33
+ }
34
+ }
35
+ // Validate actionDispositions (optional, but if present must be valid)
36
+ if (policy.actionDispositions !== undefined) {
37
+ this.validateActionDispositions(policy.actionDispositions, errors);
38
+ }
39
+ // Validate dependencyRules (optional, but if present must be valid)
40
+ if (policy.dependencyRules !== undefined) {
41
+ this.validateDependencyRules(policy.dependencyRules, errors);
42
+ }
43
+ // Validate releaseRules (optional, but if present must be valid)
44
+ if (policy.releaseRules !== undefined) {
45
+ this.validateReleaseRules(policy.releaseRules, errors);
46
+ }
47
+ return {
48
+ valid: errors.length === 0,
49
+ errors,
50
+ };
51
+ }
52
+ validateActionDispositions(value, errors) {
53
+ if (!Array.isArray(value)) {
54
+ errors.push('actionDispositions must be an array');
55
+ return;
56
+ }
57
+ if (value.length > MAX_ACTION_DISPOSITIONS) {
58
+ errors.push(`actionDispositions exceeds limit: ${value.length} entries (max ${MAX_ACTION_DISPOSITIONS})`);
59
+ return;
60
+ }
61
+ // Track categories to detect contradictions
62
+ const categoryToDisposition = new Map();
63
+ for (let i = 0; i < value.length; i++) {
64
+ const entry = value[i];
65
+ if (!entry || typeof entry !== 'object') {
66
+ errors.push(`actionDispositions[${i}] must be an object`);
67
+ continue;
68
+ }
69
+ const category = entry.category;
70
+ const disposition = entry.disposition;
71
+ if (!VALID_CATEGORIES.includes(category)) {
72
+ errors.push(`actionDispositions[${i}].category: invalid value "${String(category)}". Valid values: ${VALID_CATEGORIES.join(', ')}`);
73
+ }
74
+ if (!VALID_DISPOSITIONS.includes(disposition)) {
75
+ errors.push(`actionDispositions[${i}].disposition: invalid value "${String(disposition)}". Valid values: ${VALID_DISPOSITIONS.join(', ')}`);
76
+ }
77
+ // Check for contradictory entries (same category, different disposition)
78
+ if (VALID_CATEGORIES.includes(category) &&
79
+ VALID_DISPOSITIONS.includes(disposition)) {
80
+ const existing = categoryToDisposition.get(category);
81
+ if (existing !== undefined && existing !== disposition) {
82
+ errors.push(`Contradictory action dispositions for category "${category}": "${existing}" vs "${disposition}"`);
83
+ }
84
+ else {
85
+ categoryToDisposition.set(category, disposition);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ validateDependencyRules(value, errors) {
91
+ if (!value || typeof value !== 'object') {
92
+ errors.push('dependencyRules must be an object');
93
+ return;
94
+ }
95
+ const rules = value;
96
+ // Validate boolean fields
97
+ const booleanFields = [
98
+ 'checkLockfileConsistency',
99
+ 'checkLifecycleScripts',
100
+ 'checkNonRegistrySource',
101
+ 'enforceStrictVersionRanges',
102
+ ];
103
+ for (const field of booleanFields) {
104
+ if (rules[field] !== undefined && typeof rules[field] !== 'boolean') {
105
+ errors.push(`dependencyRules.${field} must be a boolean, got ${typeof rules[field]}`);
106
+ }
107
+ }
108
+ // Validate list fields
109
+ if (rules.allowlist !== undefined) {
110
+ this.validateStringList('dependencyRules.allowlist', rules.allowlist, errors);
111
+ }
112
+ if (rules.denylist !== undefined) {
113
+ this.validateStringList('dependencyRules.denylist', rules.denylist, errors);
114
+ }
115
+ }
116
+ validateReleaseRules(value, errors) {
117
+ if (!value || typeof value !== 'object') {
118
+ errors.push('releaseRules must be an object');
119
+ return;
120
+ }
121
+ const rules = value;
122
+ const booleanFields = [
123
+ 'requireCiOnlyPublishing',
124
+ 'requireProvenance',
125
+ 'checkWorkflowIntegrity',
126
+ ];
127
+ for (const field of booleanFields) {
128
+ if (rules[field] !== undefined && typeof rules[field] !== 'boolean') {
129
+ errors.push(`releaseRules.${field} must be a boolean, got ${typeof rules[field]}`);
130
+ }
131
+ }
132
+ }
133
+ validateStringList(path, value, errors) {
134
+ if (!Array.isArray(value)) {
135
+ errors.push(`${path} must be an array`);
136
+ return;
137
+ }
138
+ if (value.length > MAX_LIST_ENTRIES) {
139
+ errors.push(`${path} exceeds limit: ${value.length} entries (max ${MAX_LIST_ENTRIES})`);
140
+ }
141
+ for (let i = 0; i < value.length; i++) {
142
+ if (typeof value[i] !== 'string') {
143
+ errors.push(`${path}[${i}] must be a string`);
144
+ }
145
+ }
146
+ }
147
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Security Policy Service
3
+ *
4
+ * Central policy engine implementing ISecurityPolicyService.
5
+ * Reads the policy file, validates it, merges with persisted settings defaults
6
+ * using deterministic precedence, and returns an EffectivePolicySnapshot.
7
+ *
8
+ * Precedence: global settings defaults < repository policy file (stricter wins).
9
+ * A lower-precedence layer cannot weaken a stricter higher-precedence rule.
10
+ */
11
+ import { SecurityActionCategory, SecurityActionDisposition } from '../../../domain/generated/output.js';
12
+ import type { EffectivePolicySnapshot } from '../../../domain/generated/output.js';
13
+ import type { ISecurityPolicyService, PolicyValidationResult } from '../../../application/ports/output/services/security-policy-service.interface.js';
14
+ import type { ISettingsRepository } from '../../../application/ports/output/repositories/settings.repository.interface.js';
15
+ import { SecurityPolicyFileReader } from './security-policy-file-reader.js';
16
+ import { SecurityPolicyValidator } from './security-policy-validator.js';
17
+ export declare class SecurityPolicyService implements ISecurityPolicyService {
18
+ private readonly fileReader;
19
+ private readonly validator;
20
+ private readonly settingsRepo;
21
+ private readonly cache;
22
+ constructor(fileReader: SecurityPolicyFileReader, validator: SecurityPolicyValidator, settingsRepo: ISettingsRepository);
23
+ evaluatePolicy(repositoryPath: string): Promise<EffectivePolicySnapshot>;
24
+ getEffectivePolicy(repositoryPath: string): Promise<EffectivePolicySnapshot>;
25
+ validatePolicyFile(filePath: string): Promise<PolicyValidationResult>;
26
+ getActionDisposition(policy: EffectivePolicySnapshot, actionCategory: SecurityActionCategory): SecurityActionDisposition;
27
+ /**
28
+ * Build a default snapshot from settings mode only (no policy file).
29
+ */
30
+ private buildDefaultSnapshot;
31
+ /**
32
+ * Merge settings defaults with policy file, applying strict-wins precedence.
33
+ */
34
+ private mergePolicy;
35
+ /**
36
+ * Return the stricter of two SecurityMode values.
37
+ */
38
+ private stricterMode;
39
+ /**
40
+ * Return the stricter of two SecurityActionDisposition values.
41
+ */
42
+ private stricterDisposition;
43
+ }
44
+ //# sourceMappingURL=security-policy.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-policy.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/security/security-policy.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAEL,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EACV,uBAAuB,EAGxB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EACV,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,iFAAiF,CAAC;AACzF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iFAAiF,CAAC;AAC3H,OAAO,EACL,wBAAwB,EAEzB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AA4BzE,qBACa,qBAAsB,YAAW,sBAAsB;IAKhE,OAAO,CAAC,QAAQ,CAAC,UAAU;IAE3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAE1B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAR/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8C;gBAIjD,UAAU,EAAE,wBAAwB,EAEpC,SAAS,EAAE,uBAAuB,EAElC,YAAY,EAAE,mBAAmB;IAG9C,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA6BxE,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAQ5E,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAY3E,oBAAoB,CAClB,MAAM,EAAE,uBAAuB,EAC/B,cAAc,EAAE,sBAAsB,GACrC,yBAAyB;IAK5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAY5B;;OAEG;IACH,OAAO,CAAC,WAAW;IAuCnB;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAQ5B"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Security Policy Service
3
+ *
4
+ * Central policy engine implementing ISecurityPolicyService.
5
+ * Reads the policy file, validates it, merges with persisted settings defaults
6
+ * using deterministic precedence, and returns an EffectivePolicySnapshot.
7
+ *
8
+ * Precedence: global settings defaults < repository policy file (stricter wins).
9
+ * A lower-precedence layer cannot weaken a stricter higher-precedence rule.
10
+ */
11
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
12
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
13
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
14
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
15
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
16
+ };
17
+ var __metadata = (this && this.__metadata) || function (k, v) {
18
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
19
+ };
20
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
21
+ return function (target, key) { decorator(target, key, paramIndex); }
22
+ };
23
+ import { injectable, inject } from 'tsyringe';
24
+ import { SecurityMode, SecurityActionCategory, SecurityActionDisposition, } from '../../../domain/generated/output.js';
25
+ import { SecurityPolicyFileReader, SECURITY_POLICY_FILENAME, } from './security-policy-file-reader.js';
26
+ import { SecurityPolicyValidator } from './security-policy-validator.js';
27
+ import { dirname } from 'node:path';
28
+ /**
29
+ * Numeric rank for comparing SecurityMode strictness.
30
+ * Higher number = stricter mode.
31
+ */
32
+ const MODE_STRICTNESS = {
33
+ [SecurityMode.Disabled]: 0,
34
+ [SecurityMode.Advisory]: 1,
35
+ [SecurityMode.Enforce]: 2,
36
+ };
37
+ /**
38
+ * Numeric rank for comparing disposition strictness.
39
+ * Higher number = more restrictive.
40
+ */
41
+ const DISPOSITION_STRICTNESS = {
42
+ [SecurityActionDisposition.Allowed]: 0,
43
+ [SecurityActionDisposition.ApprovalRequired]: 1,
44
+ [SecurityActionDisposition.Denied]: 2,
45
+ };
46
+ /**
47
+ * All action categories for building default dispositions.
48
+ */
49
+ const ALL_CATEGORIES = Object.values(SecurityActionCategory);
50
+ let SecurityPolicyService = class SecurityPolicyService {
51
+ fileReader;
52
+ validator;
53
+ settingsRepo;
54
+ cache = new Map();
55
+ constructor(fileReader, validator, settingsRepo) {
56
+ this.fileReader = fileReader;
57
+ this.validator = validator;
58
+ this.settingsRepo = settingsRepo;
59
+ }
60
+ async evaluatePolicy(repositoryPath) {
61
+ // Load settings defaults
62
+ const settings = await this.settingsRepo.load();
63
+ const settingsMode = settings?.security?.mode ?? SecurityMode.Advisory;
64
+ // Read policy file
65
+ const policyFile = await this.fileReader.read(repositoryPath);
66
+ if (!policyFile) {
67
+ // No policy file — use settings defaults
68
+ const snapshot = this.buildDefaultSnapshot(settingsMode);
69
+ this.cache.set(repositoryPath, snapshot);
70
+ return snapshot;
71
+ }
72
+ // Validate policy file
73
+ const validation = this.validator.validate(policyFile);
74
+ if (!validation.valid) {
75
+ throw new Error(`Security policy validation failed for ${repositoryPath}:\n${validation.errors.join('\n')}`);
76
+ }
77
+ // Merge with precedence: settings defaults < policy file (stricter wins)
78
+ const snapshot = this.mergePolicy(settingsMode, policyFile);
79
+ this.cache.set(repositoryPath, snapshot);
80
+ return snapshot;
81
+ }
82
+ async getEffectivePolicy(repositoryPath) {
83
+ const cached = this.cache.get(repositoryPath);
84
+ if (cached) {
85
+ return cached;
86
+ }
87
+ return this.evaluatePolicy(repositoryPath);
88
+ }
89
+ async validatePolicyFile(filePath) {
90
+ // Read the file from the directory containing it
91
+ const dirPath = dirname(filePath);
92
+ const policyFile = await this.fileReader.read(dirPath);
93
+ if (!policyFile) {
94
+ return { valid: true, errors: [] };
95
+ }
96
+ return this.validator.validate(policyFile);
97
+ }
98
+ getActionDisposition(policy, actionCategory) {
99
+ const entry = policy.actionDispositions.find((d) => d.category === actionCategory);
100
+ return entry?.disposition ?? SecurityActionDisposition.Allowed;
101
+ }
102
+ /**
103
+ * Build a default snapshot from settings mode only (no policy file).
104
+ */
105
+ buildDefaultSnapshot(mode) {
106
+ return {
107
+ mode,
108
+ source: 'settings-default',
109
+ evaluatedAt: new Date().toISOString(),
110
+ actionDispositions: ALL_CATEGORIES.map((category) => ({
111
+ category,
112
+ disposition: SecurityActionDisposition.Allowed,
113
+ })),
114
+ };
115
+ }
116
+ /**
117
+ * Merge settings defaults with policy file, applying strict-wins precedence.
118
+ */
119
+ mergePolicy(settingsMode, policyFile) {
120
+ // Mode: stricter wins
121
+ const fileMode = policyFile.mode ?? SecurityMode.Advisory;
122
+ const effectiveMode = this.stricterMode(settingsMode, fileMode);
123
+ // Action dispositions: merge file entries with defaults, stricter wins
124
+ const dispositionMap = new Map();
125
+ // Start with defaults (all Allowed)
126
+ for (const category of ALL_CATEGORIES) {
127
+ dispositionMap.set(category, SecurityActionDisposition.Allowed);
128
+ }
129
+ // Apply policy file entries (can only make stricter, not weaker)
130
+ if (policyFile.actionDispositions) {
131
+ for (const entry of policyFile.actionDispositions) {
132
+ const current = dispositionMap.get(entry.category);
133
+ if (current !== undefined) {
134
+ dispositionMap.set(entry.category, this.stricterDisposition(current, entry.disposition));
135
+ }
136
+ }
137
+ }
138
+ const actionDispositions = [];
139
+ for (const [category, disposition] of dispositionMap) {
140
+ actionDispositions.push({ category, disposition });
141
+ }
142
+ return {
143
+ mode: effectiveMode,
144
+ source: SECURITY_POLICY_FILENAME,
145
+ evaluatedAt: new Date().toISOString(),
146
+ actionDispositions,
147
+ };
148
+ }
149
+ /**
150
+ * Return the stricter of two SecurityMode values.
151
+ */
152
+ stricterMode(a, b) {
153
+ const rankA = MODE_STRICTNESS[a] ?? 0;
154
+ const rankB = MODE_STRICTNESS[b] ?? 0;
155
+ return rankA >= rankB ? a : b;
156
+ }
157
+ /**
158
+ * Return the stricter of two SecurityActionDisposition values.
159
+ */
160
+ stricterDisposition(a, b) {
161
+ const rankA = DISPOSITION_STRICTNESS[a] ?? 0;
162
+ const rankB = DISPOSITION_STRICTNESS[b] ?? 0;
163
+ return rankA >= rankB ? a : b;
164
+ }
165
+ };
166
+ SecurityPolicyService = __decorate([
167
+ injectable(),
168
+ __param(0, inject('SecurityPolicyFileReader')),
169
+ __param(1, inject('SecurityPolicyValidator')),
170
+ __param(2, inject('ISettingsRepository')),
171
+ __metadata("design:paramtypes", [SecurityPolicyFileReader,
172
+ SecurityPolicyValidator, Object])
173
+ ], SecurityPolicyService);
174
+ export { SecurityPolicyService };