@raishin/vanguard-frontier-agentic 3.11.0 → 3.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (393) hide show
  1. package/.agents/tasks/task-rust-tui-implementation/2025-01-15-120000-review.md +1 -1
  2. package/.agents/tasks/task-rust-tui-implementation/task.json +1 -1
  3. package/.claude-plugin/marketplace.json +2 -2
  4. package/.claude-plugin/plugin.json +7 -1
  5. package/.cursor-plugin/plugin.json +25 -1
  6. package/.github/plugin/marketplace.json +1 -1
  7. package/README.md +13 -13
  8. package/agents/AGENTS.md +24 -24
  9. package/agents/README.md +17 -17
  10. package/agents/ionos/ionos-cost-optimization-analyst-agent/metadata.json +17 -3
  11. package/agents/ionos/ionos-datacenter-designer-reviewer-agent/metadata.json +17 -3
  12. package/agents/ionos/ionos-kubernetes-platform-operator-agent/metadata.json +17 -3
  13. package/agents/ionos/ionos-live-database-lifecycle-guard-agent/metadata.json +17 -3
  14. package/agents/ionos/ionos-maestro-agent/metadata.json +17 -3
  15. package/agents/ionos/ionos-security-compliance-reviewer-agent/metadata.json +17 -3
  16. package/agents/istio/README.md +16 -8
  17. package/agents/istio/istio-ambient-mesh-review-agent/AGENT.md +19 -23
  18. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/claude-code.agent.md +20 -20
  19. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/codex.toml +34 -17
  20. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/copilot.agent.md +26 -20
  21. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/cursor.agent.md +20 -20
  22. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/gemini.agent.md +20 -20
  23. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/kiro-cli.agent.json +2 -2
  24. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/kiro-ide.agent.md +20 -20
  25. package/agents/istio/istio-ambient-mesh-review-agent/metadata.json +29 -9
  26. package/agents/istio/istio-authorization-policy-review-agent/AGENT.md +51 -0
  27. package/agents/istio/istio-authorization-policy-review-agent/harnesses/claude-code.agent.md +38 -0
  28. package/agents/istio/istio-authorization-policy-review-agent/harnesses/codex.toml +49 -0
  29. package/agents/istio/istio-authorization-policy-review-agent/harnesses/copilot.agent.md +44 -0
  30. package/agents/istio/istio-authorization-policy-review-agent/harnesses/cursor.agent.md +38 -0
  31. package/agents/istio/istio-authorization-policy-review-agent/harnesses/gemini.agent.md +38 -0
  32. package/agents/istio/istio-authorization-policy-review-agent/harnesses/kiro-cli.agent.json +5 -0
  33. package/agents/istio/istio-authorization-policy-review-agent/harnesses/kiro-ide.agent.md +38 -0
  34. package/agents/istio/istio-authorization-policy-review-agent/metadata.json +50 -0
  35. package/agents/istio/istio-dataplane-diagnostics-agent/AGENT.md +51 -0
  36. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/claude-code.agent.md +38 -0
  37. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/codex.toml +49 -0
  38. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/copilot.agent.md +44 -0
  39. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/cursor.agent.md +38 -0
  40. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/gemini.agent.md +38 -0
  41. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/kiro-cli.agent.json +5 -0
  42. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/kiro-ide.agent.md +38 -0
  43. package/agents/istio/istio-dataplane-diagnostics-agent/metadata.json +50 -0
  44. package/agents/istio/istio-gateway-api-review-agent/AGENT.md +51 -0
  45. package/agents/istio/istio-gateway-api-review-agent/harnesses/claude-code.agent.md +38 -0
  46. package/agents/istio/istio-gateway-api-review-agent/harnesses/codex.toml +49 -0
  47. package/agents/istio/istio-gateway-api-review-agent/harnesses/copilot.agent.md +44 -0
  48. package/agents/istio/istio-gateway-api-review-agent/harnesses/cursor.agent.md +38 -0
  49. package/agents/istio/istio-gateway-api-review-agent/harnesses/gemini.agent.md +38 -0
  50. package/agents/istio/istio-gateway-api-review-agent/harnesses/kiro-cli.agent.json +5 -0
  51. package/agents/istio/istio-gateway-api-review-agent/harnesses/kiro-ide.agent.md +38 -0
  52. package/agents/istio/istio-gateway-api-review-agent/metadata.json +50 -0
  53. package/agents/istio/istio-maestro-agent/AGENT.md +51 -0
  54. package/agents/istio/istio-maestro-agent/harnesses/claude-code.agent.md +38 -0
  55. package/agents/istio/istio-maestro-agent/harnesses/codex.toml +49 -0
  56. package/agents/istio/istio-maestro-agent/harnesses/copilot.agent.md +44 -0
  57. package/agents/istio/istio-maestro-agent/harnesses/cursor.agent.md +38 -0
  58. package/agents/istio/istio-maestro-agent/harnesses/gemini.agent.md +38 -0
  59. package/agents/istio/istio-maestro-agent/harnesses/kiro-cli.agent.json +5 -0
  60. package/agents/istio/istio-maestro-agent/harnesses/kiro-ide.agent.md +38 -0
  61. package/agents/istio/istio-maestro-agent/metadata.json +44 -0
  62. package/agents/istio/istio-traffic-resilience-review-agent/AGENT.md +51 -0
  63. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/claude-code.agent.md +38 -0
  64. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/codex.toml +49 -0
  65. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/copilot.agent.md +44 -0
  66. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/cursor.agent.md +38 -0
  67. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/gemini.agent.md +38 -0
  68. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/kiro-cli.agent.json +5 -0
  69. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/kiro-ide.agent.md +38 -0
  70. package/agents/istio/istio-traffic-resilience-review-agent/metadata.json +50 -0
  71. package/agents/istio/istio-upgrade-readiness-agent/AGENT.md +51 -0
  72. package/agents/istio/istio-upgrade-readiness-agent/harnesses/claude-code.agent.md +38 -0
  73. package/agents/istio/istio-upgrade-readiness-agent/harnesses/codex.toml +49 -0
  74. package/agents/istio/istio-upgrade-readiness-agent/harnesses/copilot.agent.md +44 -0
  75. package/agents/istio/istio-upgrade-readiness-agent/harnesses/cursor.agent.md +38 -0
  76. package/agents/istio/istio-upgrade-readiness-agent/harnesses/gemini.agent.md +38 -0
  77. package/agents/istio/istio-upgrade-readiness-agent/harnesses/kiro-cli.agent.json +5 -0
  78. package/agents/istio/istio-upgrade-readiness-agent/harnesses/kiro-ide.agent.md +38 -0
  79. package/agents/istio/istio-upgrade-readiness-agent/metadata.json +50 -0
  80. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/AGENT.md +23 -34
  81. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/claude-code.agent.md +23 -30
  82. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/codex.toml +46 -21
  83. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/copilot.agent.md +33 -30
  84. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/cursor.agent.md +23 -30
  85. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/gemini.agent.md +23 -30
  86. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/kiro-cli.agent.json +2 -2
  87. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/kiro-ide.agent.md +23 -30
  88. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/metadata.json +9 -8
  89. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/references/rbac-pre-flight.md +9 -2
  90. package/agents/ovhcloud/ovhcloud-cost-finops-analyst-agent/metadata.json +17 -3
  91. package/agents/ovhcloud/ovhcloud-iam-policy-review-agent/metadata.json +17 -3
  92. package/agents/ovhcloud/ovhcloud-kubernetes-platform-operator-agent/metadata.json +17 -3
  93. package/agents/ovhcloud/ovhcloud-live-kms-key-destruction-guard-agent/metadata.json +17 -3
  94. package/agents/ovhcloud/ovhcloud-maestro-agent/metadata.json +17 -3
  95. package/agents/ovhcloud/ovhcloud-network-architect-agent/metadata.json +17 -3
  96. package/agents/scaleway/scaleway-cost-optimizer-agent/metadata.json +17 -3
  97. package/agents/scaleway/scaleway-iam-policy-review-agent/metadata.json +17 -3
  98. package/agents/scaleway/scaleway-kapsule-platform-operator-agent/metadata.json +17 -3
  99. package/agents/scaleway/scaleway-live-kapsule-rollout-guard-agent/metadata.json +17 -3
  100. package/agents/scaleway/scaleway-maestro-agent/metadata.json +17 -3
  101. package/agents/scaleway/scaleway-network-architect-agent/metadata.json +17 -3
  102. package/catalog/agents.json +378 -113
  103. package/catalog/asset-integrity.json +1268 -138
  104. package/catalog/install-roles.json +14 -1
  105. package/catalog/model-assignments.json +198 -0
  106. package/catalog/model-registry.json +70 -34
  107. package/catalog/skill-manifest.json +517 -13
  108. package/catalog/skills.json +213 -8
  109. package/catalog/workflows.json +49 -0
  110. package/package.json +7 -4
  111. package/plugins/cross-platform-agent-template/LICENSE +201 -0
  112. package/plugins/cross-platform-agent-template/README.md +30 -0
  113. package/plugins/cross-platform-agent-template/SECURITY.md +18 -0
  114. package/plugins/vanguard-frontier-agentic/.codex-plugin/plugin.json +1 -1
  115. package/powers/README.md +5 -2
  116. package/powers/vanguard-istio/POWER.md +6 -5
  117. package/schemas/istio-review-contract.schema.json +284 -0
  118. package/schemas/model-policy.schema.json +1 -1
  119. package/scripts/generate-board-counts.mjs +40 -4
  120. package/scripts/generate-readme-counts.mjs +51 -2
  121. package/scripts/generate-workflow-catalog.mjs +7 -7
  122. package/scripts/istio_evidence_facts.py +359 -0
  123. package/scripts/model-policy.mjs +74 -11
  124. package/skills/istio/README.md +15 -4
  125. package/skills/istio/istio-ambient-mesh-review/SKILL.md +38 -39
  126. package/skills/istio/istio-ambient-mesh-review/agents/openai.yaml +5 -0
  127. package/skills/istio/istio-ambient-mesh-review/metadata.json +8 -8
  128. package/skills/istio/istio-ambient-mesh-review/references/applicability.md +9 -0
  129. package/skills/istio/istio-ambient-mesh-review/references/enforcement-rules.md +21 -0
  130. package/skills/istio/istio-ambient-mesh-review/references/enrollment-and-paths.md +27 -0
  131. package/skills/istio/istio-ambient-mesh-review/references/evidence-boundary.md +33 -0
  132. package/skills/istio/istio-ambient-mesh-review/references/migration-boundaries.md +19 -0
  133. package/skills/istio/istio-ambient-mesh-review/references/negative-tests.md +15 -0
  134. package/skills/istio/istio-ambient-mesh-review/references/official-sources.md +33 -32
  135. package/skills/istio/istio-ambient-mesh-review/references/output-contract.md +21 -0
  136. package/skills/istio/istio-ambient-mesh-review/references/review-contract.json +284 -0
  137. package/skills/istio/istio-authorization-policy-review/SKILL.md +44 -0
  138. package/skills/istio/istio-authorization-policy-review/agents/openai.yaml +5 -0
  139. package/skills/istio/istio-authorization-policy-review/metadata.json +30 -0
  140. package/skills/istio/istio-authorization-policy-review/references/applicability.md +9 -0
  141. package/skills/istio/istio-authorization-policy-review/references/authentication-and-identity.md +21 -0
  142. package/skills/istio/istio-authorization-policy-review/references/evidence-boundary.md +33 -0
  143. package/skills/istio/istio-authorization-policy-review/references/negative-tests.md +15 -0
  144. package/skills/istio/istio-authorization-policy-review/references/official-sources.md +33 -0
  145. package/skills/istio/istio-authorization-policy-review/references/output-contract.md +21 -0
  146. package/skills/istio/istio-authorization-policy-review/references/policy-set-semantics.md +21 -0
  147. package/skills/istio/istio-authorization-policy-review/references/protocol-and-normalization.md +19 -0
  148. package/skills/istio/istio-authorization-policy-review/references/review-contract.json +284 -0
  149. package/skills/istio/istio-dataplane-diagnostics/SKILL.md +45 -0
  150. package/skills/istio/istio-dataplane-diagnostics/agents/openai.yaml +5 -0
  151. package/skills/istio/istio-dataplane-diagnostics/metadata.json +30 -0
  152. package/skills/istio/istio-dataplane-diagnostics/references/applicability.md +9 -0
  153. package/skills/istio/istio-dataplane-diagnostics/references/collection-and-offline-analysis.md +17 -0
  154. package/skills/istio/istio-dataplane-diagnostics/references/evidence-boundary.md +33 -0
  155. package/skills/istio/istio-dataplane-diagnostics/references/hypothesis-workflow.md +19 -0
  156. package/skills/istio/istio-dataplane-diagnostics/references/negative-tests.md +13 -0
  157. package/skills/istio/istio-dataplane-diagnostics/references/official-sources.md +33 -0
  158. package/skills/istio/istio-dataplane-diagnostics/references/output-contract.md +21 -0
  159. package/skills/istio/istio-dataplane-diagnostics/references/review-contract.json +284 -0
  160. package/skills/istio/istio-dataplane-diagnostics/references/signal-interpretation.md +15 -0
  161. package/skills/istio/istio-gateway-api-review/SKILL.md +45 -0
  162. package/skills/istio/istio-gateway-api-review/agents/openai.yaml +5 -0
  163. package/skills/istio/istio-gateway-api-review/metadata.json +30 -0
  164. package/skills/istio/istio-gateway-api-review/references/applicability.md +9 -0
  165. package/skills/istio/istio-gateway-api-review/references/attachment-graph.md +19 -0
  166. package/skills/istio/istio-gateway-api-review/references/conditions-and-freshness.md +15 -0
  167. package/skills/istio/istio-gateway-api-review/references/evidence-boundary.md +33 -0
  168. package/skills/istio/istio-gateway-api-review/references/negative-tests.md +12 -0
  169. package/skills/istio/istio-gateway-api-review/references/official-sources.md +33 -0
  170. package/skills/istio/istio-gateway-api-review/references/output-contract.md +21 -0
  171. package/skills/istio/istio-gateway-api-review/references/review-contract.json +284 -0
  172. package/skills/istio/istio-gateway-api-review/references/tls-and-boundaries.md +17 -0
  173. package/skills/istio/istio-live-policy-change/SKILL.md +45 -0
  174. package/skills/istio/istio-live-policy-change/agents/openai.yaml +7 -0
  175. package/skills/istio/istio-live-policy-change/metadata.json +29 -0
  176. package/skills/istio/istio-live-policy-change/references/applicability.md +9 -0
  177. package/skills/istio/istio-live-policy-change/references/approval-and-scope.md +17 -0
  178. package/skills/istio/istio-live-policy-change/references/evidence-boundary.md +33 -0
  179. package/skills/istio/istio-live-policy-change/references/execution-protocol.md +19 -0
  180. package/skills/istio/istio-live-policy-change/references/negative-tests.md +12 -0
  181. package/skills/istio/istio-live-policy-change/references/official-sources.md +27 -0
  182. package/skills/istio/istio-live-policy-change/references/output-contract.md +21 -0
  183. package/skills/istio/istio-live-policy-change/references/review-contract.json +284 -0
  184. package/skills/istio/istio-live-policy-change/references/rollback-and-verification.md +19 -0
  185. package/skills/istio/istio-review-routing/SKILL.md +45 -0
  186. package/skills/istio/istio-review-routing/agents/openai.yaml +5 -0
  187. package/skills/istio/istio-review-routing/metadata.json +26 -0
  188. package/skills/istio/istio-review-routing/references/aggregation-and-conflicts.md +15 -0
  189. package/skills/istio/istio-review-routing/references/applicability.md +9 -0
  190. package/skills/istio/istio-review-routing/references/evidence-boundary.md +33 -0
  191. package/skills/istio/istio-review-routing/references/live-handoff.md +11 -0
  192. package/skills/istio/istio-review-routing/references/negative-tests.md +11 -0
  193. package/skills/istio/istio-review-routing/references/official-sources.md +9 -0
  194. package/skills/istio/istio-review-routing/references/output-contract.md +21 -0
  195. package/skills/istio/istio-review-routing/references/review-contract.json +284 -0
  196. package/skills/istio/istio-review-routing/references/routing-table.md +18 -0
  197. package/skills/istio/istio-traffic-resilience-review/SKILL.md +45 -0
  198. package/skills/istio/istio-traffic-resilience-review/agents/openai.yaml +5 -0
  199. package/skills/istio/istio-traffic-resilience-review/metadata.json +30 -0
  200. package/skills/istio/istio-traffic-resilience-review/references/applicability.md +9 -0
  201. package/skills/istio/istio-traffic-resilience-review/references/evidence-boundary.md +33 -0
  202. package/skills/istio/istio-traffic-resilience-review/references/mirroring-and-faults.md +15 -0
  203. package/skills/istio/istio-traffic-resilience-review/references/negative-tests.md +14 -0
  204. package/skills/istio/istio-traffic-resilience-review/references/official-sources.md +33 -0
  205. package/skills/istio/istio-traffic-resilience-review/references/output-contract.md +21 -0
  206. package/skills/istio/istio-traffic-resilience-review/references/review-contract.json +284 -0
  207. package/skills/istio/istio-traffic-resilience-review/references/routing-and-weights.md +19 -0
  208. package/skills/istio/istio-traffic-resilience-review/references/timeouts-retries-and-capacity.md +21 -0
  209. package/skills/istio/istio-upgrade-readiness/SKILL.md +45 -0
  210. package/skills/istio/istio-upgrade-readiness/agents/openai.yaml +5 -0
  211. package/skills/istio/istio-upgrade-readiness/metadata.json +30 -0
  212. package/skills/istio/istio-upgrade-readiness/references/applicability.md +9 -0
  213. package/skills/istio/istio-upgrade-readiness/references/crds-extensions-and-rollback.md +17 -0
  214. package/skills/istio/istio-upgrade-readiness/references/evidence-boundary.md +33 -0
  215. package/skills/istio/istio-upgrade-readiness/references/inventory-and-support.md +17 -0
  216. package/skills/istio/istio-upgrade-readiness/references/negative-tests.md +13 -0
  217. package/skills/istio/istio-upgrade-readiness/references/official-sources.md +33 -0
  218. package/skills/istio/istio-upgrade-readiness/references/output-contract.md +21 -0
  219. package/skills/istio/istio-upgrade-readiness/references/review-contract.json +284 -0
  220. package/skills/istio/istio-upgrade-readiness/references/skew-and-order.md +19 -0
  221. package/tests/fixtures/README.md +1 -1
  222. package/tests/fixtures/istio-maestro-routing/expected/001-happy-ambient-mesh-review.json +6 -0
  223. package/tests/fixtures/istio-maestro-routing/expected/002-happy-authorization-policy-review.json +6 -0
  224. package/tests/fixtures/istio-maestro-routing/expected/003-happy-dataplane-diagnostics.json +6 -0
  225. package/tests/fixtures/istio-maestro-routing/expected/004-happy-gateway-api-review.json +6 -0
  226. package/tests/fixtures/istio-maestro-routing/expected/005-happy-traffic-resilience-review.json +6 -0
  227. package/tests/fixtures/istio-maestro-routing/expected/006-happy-upgrade-readiness.json +6 -0
  228. package/tests/fixtures/istio-maestro-routing/expected/adv-ambiguous.json +4 -0
  229. package/tests/fixtures/istio-maestro-routing/expected/adv-instruction-injection.json +6 -0
  230. package/tests/fixtures/istio-maestro-routing/expected/adv-liveguard-01-kubernetes-live-mesh-policy-guard.json +6 -0
  231. package/tests/fixtures/istio-maestro-routing/expected/adv-persona-replacement.json +6 -0
  232. package/tests/fixtures/istio-maestro-routing/expected/adv-secrets-bait.json +6 -0
  233. package/tests/fixtures/istio-maestro-routing/expected/live-create-authorization-policy.json +6 -0
  234. package/tests/fixtures/istio-maestro-routing/expected/live-istio-gateway-apply.json +6 -0
  235. package/tests/fixtures/istio-maestro-routing/expected/live-kubectl-file-apply.json +6 -0
  236. package/tests/fixtures/istio-maestro-routing/expected/live-label-peer-authentication.json +6 -0
  237. package/tests/fixtures/istio-maestro-routing/expected/live-multiline-patch.json +6 -0
  238. package/tests/fixtures/istio-maestro-routing/expected/live-qualified-plural-delete.json +6 -0
  239. package/tests/fixtures/istio-maestro-routing/expected/live-resource-first-apply.json +6 -0
  240. package/tests/fixtures/istio-maestro-routing/expected/live-set-peer-authentication.json +6 -0
  241. package/tests/fixtures/istio-maestro-routing/expected/negative-product-identification.json +4 -0
  242. package/tests/fixtures/istio-maestro-routing/expected/negative-review-apply-safety.json +6 -0
  243. package/tests/fixtures/istio-maestro-routing/inputs/001-happy-ambient-mesh-review.json +7 -0
  244. package/tests/fixtures/istio-maestro-routing/inputs/002-happy-authorization-policy-review.json +7 -0
  245. package/tests/fixtures/istio-maestro-routing/inputs/003-happy-dataplane-diagnostics.json +7 -0
  246. package/tests/fixtures/istio-maestro-routing/inputs/004-happy-gateway-api-review.json +7 -0
  247. package/tests/fixtures/istio-maestro-routing/inputs/005-happy-traffic-resilience-review.json +7 -0
  248. package/tests/fixtures/istio-maestro-routing/inputs/006-happy-upgrade-readiness.json +7 -0
  249. package/tests/fixtures/istio-maestro-routing/inputs/adv-ambiguous.json +7 -0
  250. package/tests/fixtures/istio-maestro-routing/inputs/adv-instruction-injection.json +7 -0
  251. package/tests/fixtures/istio-maestro-routing/inputs/adv-liveguard-01-kubernetes-live-mesh-policy-guard.json +7 -0
  252. package/tests/fixtures/istio-maestro-routing/inputs/adv-persona-replacement.json +7 -0
  253. package/tests/fixtures/istio-maestro-routing/inputs/adv-secrets-bait.json +7 -0
  254. package/tests/fixtures/istio-maestro-routing/inputs/live-create-authorization-policy.json +8 -0
  255. package/tests/fixtures/istio-maestro-routing/inputs/live-istio-gateway-apply.json +8 -0
  256. package/tests/fixtures/istio-maestro-routing/inputs/live-kubectl-file-apply.json +8 -0
  257. package/tests/fixtures/istio-maestro-routing/inputs/live-label-peer-authentication.json +8 -0
  258. package/tests/fixtures/istio-maestro-routing/inputs/live-multiline-patch.json +8 -0
  259. package/tests/fixtures/istio-maestro-routing/inputs/live-qualified-plural-delete.json +8 -0
  260. package/tests/fixtures/istio-maestro-routing/inputs/live-resource-first-apply.json +8 -0
  261. package/tests/fixtures/istio-maestro-routing/inputs/live-set-peer-authentication.json +8 -0
  262. package/tests/fixtures/istio-maestro-routing/inputs/negative-product-identification.json +8 -0
  263. package/tests/fixtures/istio-maestro-routing/inputs/negative-review-apply-safety.json +8 -0
  264. package/tests/fixtures/istio-maestro-routing/taxonomy.json +129 -0
  265. package/tests/fixtures/istio-review-evals/README.md +11 -0
  266. package/tests/fixtures/istio-review-evals/expected/AMB-01.json +24 -0
  267. package/tests/fixtures/istio-review-evals/expected/AMB-02.json +24 -0
  268. package/tests/fixtures/istio-review-evals/expected/AMB-03.json +24 -0
  269. package/tests/fixtures/istio-review-evals/expected/AMB-04.json +24 -0
  270. package/tests/fixtures/istio-review-evals/expected/AMB-05.json +24 -0
  271. package/tests/fixtures/istio-review-evals/expected/AMB-06.json +24 -0
  272. package/tests/fixtures/istio-review-evals/expected/AMB-07.json +24 -0
  273. package/tests/fixtures/istio-review-evals/expected/AUTH-01.json +24 -0
  274. package/tests/fixtures/istio-review-evals/expected/AUTH-02A.json +24 -0
  275. package/tests/fixtures/istio-review-evals/expected/AUTH-02B.json +24 -0
  276. package/tests/fixtures/istio-review-evals/expected/AUTH-03.json +24 -0
  277. package/tests/fixtures/istio-review-evals/expected/AUTH-04.json +24 -0
  278. package/tests/fixtures/istio-review-evals/expected/AUTH-05.json +24 -0
  279. package/tests/fixtures/istio-review-evals/expected/AUTH-06.json +24 -0
  280. package/tests/fixtures/istio-review-evals/expected/AUTH-07.json +24 -0
  281. package/tests/fixtures/istio-review-evals/expected/AUTH-08.json +24 -0
  282. package/tests/fixtures/istio-review-evals/expected/DIAG-01.json +24 -0
  283. package/tests/fixtures/istio-review-evals/expected/DIAG-02.json +24 -0
  284. package/tests/fixtures/istio-review-evals/expected/DIAG-03.json +24 -0
  285. package/tests/fixtures/istio-review-evals/expected/DIAG-04.json +24 -0
  286. package/tests/fixtures/istio-review-evals/expected/DIAG-05.json +24 -0
  287. package/tests/fixtures/istio-review-evals/expected/GATEWAY-01.json +24 -0
  288. package/tests/fixtures/istio-review-evals/expected/GATEWAY-02A.json +24 -0
  289. package/tests/fixtures/istio-review-evals/expected/GATEWAY-02B.json +24 -0
  290. package/tests/fixtures/istio-review-evals/expected/GATEWAY-03.json +24 -0
  291. package/tests/fixtures/istio-review-evals/expected/GATEWAY-04.json +24 -0
  292. package/tests/fixtures/istio-review-evals/expected/GATEWAY-05.json +24 -0
  293. package/tests/fixtures/istio-review-evals/expected/GUARD-01.json +24 -0
  294. package/tests/fixtures/istio-review-evals/expected/GUARD-02.json +24 -0
  295. package/tests/fixtures/istio-review-evals/expected/GUARD-03.json +24 -0
  296. package/tests/fixtures/istio-review-evals/expected/GUARD-04.json +24 -0
  297. package/tests/fixtures/istio-review-evals/expected/GUARD-05.json +24 -0
  298. package/tests/fixtures/istio-review-evals/expected/GUARD-06.json +24 -0
  299. package/tests/fixtures/istio-review-evals/expected/ROUTE-01.json +24 -0
  300. package/tests/fixtures/istio-review-evals/expected/ROUTE-02.json +24 -0
  301. package/tests/fixtures/istio-review-evals/expected/ROUTE-03.json +24 -0
  302. package/tests/fixtures/istio-review-evals/expected/ROUTE-04.json +24 -0
  303. package/tests/fixtures/istio-review-evals/expected/ROUTE-05.json +24 -0
  304. package/tests/fixtures/istio-review-evals/expected/SAFETY-01.json +24 -0
  305. package/tests/fixtures/istio-review-evals/expected/SAFETY-02.json +24 -0
  306. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-01A.json +24 -0
  307. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-01B.json +24 -0
  308. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-02.json +24 -0
  309. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-03.json +24 -0
  310. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-04.json +24 -0
  311. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-05.json +24 -0
  312. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-06.json +24 -0
  313. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-07.json +24 -0
  314. package/tests/fixtures/istio-review-evals/expected/UPGRADE-01.json +24 -0
  315. package/tests/fixtures/istio-review-evals/expected/UPGRADE-02A.json +24 -0
  316. package/tests/fixtures/istio-review-evals/expected/UPGRADE-02B.json +24 -0
  317. package/tests/fixtures/istio-review-evals/expected/UPGRADE-03.json +24 -0
  318. package/tests/fixtures/istio-review-evals/expected/UPGRADE-04.json +24 -0
  319. package/tests/fixtures/istio-review-evals/expected/UPGRADE-05.json +24 -0
  320. package/tests/fixtures/istio-review-evals/expected/UPGRADE-06.json +24 -0
  321. package/tests/fixtures/istio-review-evals/inputs/AMB-01.json +20 -0
  322. package/tests/fixtures/istio-review-evals/inputs/AMB-02.json +22 -0
  323. package/tests/fixtures/istio-review-evals/inputs/AMB-03.json +39 -0
  324. package/tests/fixtures/istio-review-evals/inputs/AMB-04.json +21 -0
  325. package/tests/fixtures/istio-review-evals/inputs/AMB-05.json +20 -0
  326. package/tests/fixtures/istio-review-evals/inputs/AMB-06.json +19 -0
  327. package/tests/fixtures/istio-review-evals/inputs/AMB-07.json +17 -0
  328. package/tests/fixtures/istio-review-evals/inputs/AUTH-01.json +27 -0
  329. package/tests/fixtures/istio-review-evals/inputs/AUTH-02A.json +22 -0
  330. package/tests/fixtures/istio-review-evals/inputs/AUTH-02B.json +19 -0
  331. package/tests/fixtures/istio-review-evals/inputs/AUTH-03.json +30 -0
  332. package/tests/fixtures/istio-review-evals/inputs/AUTH-04.json +23 -0
  333. package/tests/fixtures/istio-review-evals/inputs/AUTH-05.json +22 -0
  334. package/tests/fixtures/istio-review-evals/inputs/AUTH-06.json +22 -0
  335. package/tests/fixtures/istio-review-evals/inputs/AUTH-07.json +30 -0
  336. package/tests/fixtures/istio-review-evals/inputs/AUTH-08.json +21 -0
  337. package/tests/fixtures/istio-review-evals/inputs/DIAG-01.json +18 -0
  338. package/tests/fixtures/istio-review-evals/inputs/DIAG-02.json +14 -0
  339. package/tests/fixtures/istio-review-evals/inputs/DIAG-03.json +16 -0
  340. package/tests/fixtures/istio-review-evals/inputs/DIAG-04.json +16 -0
  341. package/tests/fixtures/istio-review-evals/inputs/DIAG-05.json +16 -0
  342. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-01.json +29 -0
  343. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-02A.json +21 -0
  344. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-02B.json +17 -0
  345. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-03.json +22 -0
  346. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-04.json +22 -0
  347. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-05.json +16 -0
  348. package/tests/fixtures/istio-review-evals/inputs/GUARD-01.json +19 -0
  349. package/tests/fixtures/istio-review-evals/inputs/GUARD-02.json +16 -0
  350. package/tests/fixtures/istio-review-evals/inputs/GUARD-03.json +16 -0
  351. package/tests/fixtures/istio-review-evals/inputs/GUARD-04.json +20 -0
  352. package/tests/fixtures/istio-review-evals/inputs/GUARD-05.json +16 -0
  353. package/tests/fixtures/istio-review-evals/inputs/GUARD-06.json +16 -0
  354. package/tests/fixtures/istio-review-evals/inputs/ROUTE-01.json +16 -0
  355. package/tests/fixtures/istio-review-evals/inputs/ROUTE-02.json +18 -0
  356. package/tests/fixtures/istio-review-evals/inputs/ROUTE-03.json +15 -0
  357. package/tests/fixtures/istio-review-evals/inputs/ROUTE-04.json +25 -0
  358. package/tests/fixtures/istio-review-evals/inputs/ROUTE-05.json +15 -0
  359. package/tests/fixtures/istio-review-evals/inputs/SAFETY-01.json +14 -0
  360. package/tests/fixtures/istio-review-evals/inputs/SAFETY-02.json +15 -0
  361. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-01A.json +23 -0
  362. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-01B.json +17 -0
  363. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-02.json +19 -0
  364. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-03.json +28 -0
  365. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-04.json +18 -0
  366. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-05.json +18 -0
  367. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-06.json +18 -0
  368. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-07.json +17 -0
  369. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-01.json +19 -0
  370. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-02A.json +23 -0
  371. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-02B.json +17 -0
  372. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-03.json +21 -0
  373. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-04.json +16 -0
  374. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-05.json +33 -0
  375. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-06.json +17 -0
  376. package/tests/fixtures/istio-review-evals/manifest.json +337 -0
  377. package/tests/fixtures/runtime-semantics/README.md +3 -0
  378. package/tests/fixtures/runtime-semantics/RUNTIME-AMB-L7.json +35 -0
  379. package/tests/fixtures/runtime-semantics/RUNTIME-AUTH-EMPTY.json +33 -0
  380. package/tests/fixtures/runtime-semantics/RUNTIME-GATEWAY.json +35 -0
  381. package/tests/fixtures/runtime-semantics/RUNTIME-JWT.json +34 -0
  382. package/tests/fixtures/runtime-semantics/RUNTIME-MIGRATION.json +35 -0
  383. package/tests/fixtures/runtime-semantics/RUNTIME-MIRROR.json +33 -0
  384. package/tests/fixtures/runtime-semantics/RUNTIME-UPGRADE.json +34 -0
  385. package/tests/integration/rbac-pre-flight/guards/mesh-policy.sh +9 -2
  386. package/tests/istio-review-suite/test_contract.py +121 -0
  387. package/tests/istio-review-suite/test_evidence_facts.py +344 -0
  388. package/tests/validate-catalog.py +156 -0
  389. package/tests/validate-model-params.py +161 -0
  390. package/tests/validate-readme-counts.mjs +58 -2
  391. package/tests/validate-release-notes.mjs +35 -0
  392. package/skills/istio/istio-ambient-mesh-review/references/mcp-and-evidence.md +0 -59
  393. package/skills/istio/istio-ambient-mesh-review/references/workflow-and-output.md +0 -128
@@ -0,0 +1,34 @@
1
+ {
2
+ "id": "RUNTIME-UPGRADE",
3
+ "title": "Pinned source/target transition and rollback",
4
+ "status": "not-run",
5
+ "required_authorization": "Separate explicit environment and experiment authorization; no automated provisioning is included",
6
+ "preconditions": [
7
+ "Explicit supported source/target binaries/images/CRDs",
8
+ "Disposable topology with no shared production resources"
9
+ ],
10
+ "procedure": [
11
+ "Verify component inventory and installation-specific dependency order",
12
+ "Test staged rollout and data-plane convergence",
13
+ "Test shared CRD/extension effects and separately approved rollback limits"
14
+ ],
15
+ "acceptance": [
16
+ "Numeric skew does not replace lifecycle/support and actual operation evidence"
17
+ ],
18
+ "capture": [
19
+ "Pinned versions/digests",
20
+ "Target identities and timestamps",
21
+ "Sanitized before/after objects",
22
+ "Positive and negative traffic results",
23
+ "Path/enforcement correlation",
24
+ "Residual risk and cleanup evidence"
25
+ ],
26
+ "stop_conditions": [
27
+ "Unexpected external destination",
28
+ "Unknown target identity",
29
+ "Unapproved scope change",
30
+ "Loss of observability",
31
+ "Unresolved critical acceptance failure"
32
+ ],
33
+ "cleanup": "Use only separately approved ownership-aware cleanup. Verify teardown without deleting unrelated resources."
34
+ }
@@ -22,6 +22,9 @@ run_guard_mesh_policy() {
22
22
  # Istio CRDs may not exist in vanilla kind
23
23
  assert_cannot_or_skip delete authorizationpolicies.security.istio.io --all-namespaces "--as=$SA"
24
24
  assert_cannot_or_skip delete peerauthentications.security.istio.io --all-namespaces "--as=$SA"
25
+ assert_cannot_or_skip delete requestauthentications.security.istio.io --all-namespaces "--as=$SA"
26
+ assert_cannot_or_skip delete virtualservices.networking.istio.io --all-namespaces "--as=$SA"
27
+ assert_cannot_or_skip delete destinationrules.networking.istio.io --all-namespaces "--as=$SA"
25
28
 
26
29
  # istio-system control plane — core resources always present even without Istio CRDs
27
30
  assert_cannot patch deployments -n istio-system "--as=$SA"
@@ -41,8 +44,12 @@ run_guard_mesh_policy() {
41
44
  assert_can_or_skip patch authorizationpolicies.security.istio.io --all-namespaces "--as=$SA"
42
45
  assert_can_or_skip create peerauthentications.security.istio.io --all-namespaces "--as=$SA"
43
46
  assert_can_or_skip patch peerauthentications.security.istio.io --all-namespaces "--as=$SA"
44
- assert_can_or_skip list virtualservices.networking.istio.io --all-namespaces "--as=$SA"
45
- assert_can_or_skip list peerauthentications.security.istio.io --all-namespaces "--as=$SA"
47
+ assert_can_or_skip create requestauthentications.security.istio.io --all-namespaces "--as=$SA"
48
+ assert_can_or_skip patch requestauthentications.security.istio.io --all-namespaces "--as=$SA"
49
+ assert_can_or_skip create virtualservices.networking.istio.io --all-namespaces "--as=$SA"
50
+ assert_can_or_skip patch virtualservices.networking.istio.io --all-namespaces "--as=$SA"
51
+ assert_can_or_skip create destinationrules.networking.istio.io --all-namespaces "--as=$SA"
52
+ assert_can_or_skip patch destinationrules.networking.istio.io --all-namespaces "--as=$SA"
46
53
 
47
54
  report_guard "mesh-policy"
48
55
  }
@@ -0,0 +1,121 @@
1
+ """Native Istio review-suite contract and integration tests."""
2
+ import json
3
+ from pathlib import Path
4
+ import re
5
+ import unittest
6
+ import jsonschema
7
+
8
+ ROOT = Path(__file__).resolve().parents[2]
9
+ SKILLS = [
10
+ "istio-ambient-mesh-review", "istio-authorization-policy-review",
11
+ "istio-traffic-resilience-review", "istio-gateway-api-review",
12
+ "istio-upgrade-readiness", "istio-dataplane-diagnostics",
13
+ "istio-review-routing", "istio-live-policy-change",
14
+ ]
15
+ AGENTS = {
16
+ "istio-ambient-mesh-review": ("istio", "istio-ambient-mesh-review-agent"),
17
+ "istio-authorization-policy-review": ("istio", "istio-authorization-policy-review-agent"),
18
+ "istio-traffic-resilience-review": ("istio", "istio-traffic-resilience-review-agent"),
19
+ "istio-gateway-api-review": ("istio", "istio-gateway-api-review-agent"),
20
+ "istio-upgrade-readiness": ("istio", "istio-upgrade-readiness-agent"),
21
+ "istio-dataplane-diagnostics": ("istio", "istio-dataplane-diagnostics-agent"),
22
+ "istio-review-routing": ("istio", "istio-maestro-agent"),
23
+ "istio-live-policy-change": ("kubernetes", "kubernetes-live-mesh-policy-guard-agent"),
24
+ }
25
+
26
+ def review():
27
+ return {
28
+ "schema_version": "1.0", "skill_id": "istio-authorization-policy-review",
29
+ "verdict": "needs-review", "execution_tier": "static-review",
30
+ "scope": {"question": "Which rule-list shape is present?", "environment": "synthetic fixture", "evidence_boundary": "one supplied policy; no runtime evidence"},
31
+ "claims": [{"id": "claim-1", "classification": "derived", "statement": "The supplied list has zero rules.", "evidence_refs": ["policy.json#/spec/rules"], "applicability": "Structural list shape only", "rule_id": "AUTH-02"}],
32
+ "tests": [{"id": "test-1", "state": "proposed", "expected": "Record intended positive and negative traffic behavior.", "observed": None, "evidence_refs": []}],
33
+ "limitations": ["No runtime enforcement was observed."],
34
+ }
35
+
36
+ class ReviewContractTests(unittest.TestCase):
37
+ @classmethod
38
+ def setUpClass(cls):
39
+ cls.validator=jsonschema.Draft202012Validator(json.loads((ROOT/"schemas/istio-review-contract.schema.json").read_text()))
40
+ def rejects(self,data): self.assertTrue(list(self.validator.iter_errors(data)))
41
+ def test_bounded_review_valid(self): self.validator.validate(review())
42
+ def test_derived_claim_requires_evidence(self):
43
+ data=review(); data["claims"][0]["evidence_refs"]=[]; self.rejects(data)
44
+ def test_proposed_test_cannot_claim_observed_result(self):
45
+ data=review(); data["tests"][0]["observed"]="passed"; self.rejects(data)
46
+ def test_passed_test_requires_observation_and_evidence(self):
47
+ data=review(); data["tests"][0]["state"]="passed"; self.rejects(data)
48
+ def test_review_cannot_claim_execution_authority(self):
49
+ data=review(); data["authorized"]=True; self.rejects(data)
50
+ def test_approved_review_requires_positive_and_negative_tests(self):
51
+ data=review(); data["verdict"]="approved"; data["tests"]=[]; self.rejects(data)
52
+ data["tests"]=[review()["tests"][0]]; self.rejects(data)
53
+ second=dict(data["tests"][0]); second["id"]="test-2"; data["tests"].append(second)
54
+ self.validator.validate(data)
55
+
56
+ class NativeIntegrationTests(unittest.TestCase):
57
+ def test_all_skill_agent_bindings_resolve(self):
58
+ for skill in SKILLS:
59
+ with self.subTest(skill=skill):
60
+ sm=json.loads((ROOT/f"skills/istio/{skill}/metadata.json").read_text())
61
+ provider,agent=AGENTS[skill]
62
+ am=json.loads((ROOT/f"agents/{provider}/{agent}/metadata.json").read_text())
63
+ self.assertEqual(sm["id"],skill)
64
+ self.assertEqual(am["companion_skills"],[skill])
65
+ self.assertTrue((ROOT/f"skills/istio/{skill}/SKILL.md").is_file())
66
+ def test_static_agents_are_read_only(self):
67
+ for skill,(provider,agent) in AGENTS.items():
68
+ if skill=="istio-live-policy-change": continue
69
+ text=(ROOT/f"agents/{provider}/{agent}/harnesses/codex.toml").read_text()
70
+ self.assertIn('sandbox_mode = "read-only"',text)
71
+ def test_live_guard_is_not_duplicated(self):
72
+ matches=list((ROOT/"agents").glob("**/kubernetes-live-mesh-policy-guard-agent"))
73
+ self.assertEqual(len(matches),1)
74
+ meta=json.loads((matches[0]/"metadata.json").read_text())
75
+ self.assertEqual(meta["companion_skills"],["istio-live-policy-change"])
76
+ def test_live_guard_preflight_covers_every_writable_istio_resource(self):
77
+ guard=ROOT/"agents/kubernetes/kubernetes-live-mesh-policy-guard-agent"
78
+ docs=(guard/"references/rbac-pre-flight.md").read_text()
79
+ script=(ROOT/"tests/integration/rbac-pre-flight/guards/mesh-policy.sh").read_text()
80
+ rbac=(guard/"references/least-privilege-rbac.yaml").read_text()
81
+ rules=re.findall(
82
+ r'^ - apiGroups: (\[[^\n]+\])\n resources: (\[[^\n]+\])\n verbs: (\[[^\n]+\])$',
83
+ rbac,
84
+ re.MULTILINE,
85
+ )
86
+ writable={
87
+ f"{resource}.{json.loads(api_groups)[0]}"
88
+ for api_groups,resources,verbs in rules
89
+ if set(json.loads(verbs)) & {"create", "patch"}
90
+ for resource in json.loads(resources)
91
+ }
92
+ self.assertEqual(len(writable),5)
93
+ for resource in writable:
94
+ with self.subTest(resource=resource):
95
+ for source in (docs, script):
96
+ self.assertIn(f"delete {resource}", source)
97
+ self.assertIn(f"create {resource}", source)
98
+ self.assertIn(f"patch {resource}", source)
99
+ def test_gateway_mutations_use_the_network_architecture_guard(self):
100
+ agent=ROOT/"agents/istio/istio-gateway-api-review-agent/AGENT.md"
101
+ text=agent.read_text()
102
+ self.assertIn("kubernetes-live-network-architecture-mutation-guard-agent",text)
103
+ self.assertNotIn("kubernetes-live-mesh-policy-guard-agent",text)
104
+ rbac=(ROOT/"skills/kubernetes/kubernetes-live-network-architecture-mutation-guard/references/least-privilege-rbac.yaml").read_text()
105
+ self.assertRegex(rbac,r'(?s)apiGroups: \["gateway\.networking\.k8s\.io"\]\n resources:.*?"gateways".*?verbs: \["create", "patch"\]')
106
+ def test_live_policy_skill_requires_explicit_invocation(self):
107
+ manifest=(ROOT/"skills/istio/istio-live-policy-change/agents/openai.yaml").read_text()
108
+ self.assertRegex(manifest,r'(?m)^policy:\n allow_implicit_invocation: false$')
109
+ def test_semantic_eval_corpus_remains_unperformed(self):
110
+ paths=list((ROOT/"tests/fixtures/istio-review-evals/expected").glob("*.json"))
111
+ self.assertEqual(len(paths),55)
112
+ for path in paths:
113
+ self.assertEqual(json.loads(path.read_text())["run_status"],"not-run",path)
114
+ def test_runtime_specs_remain_unperformed(self):
115
+ paths=list((ROOT/"tests/fixtures/runtime-semantics").glob("*.json"))
116
+ self.assertEqual(len(paths),7)
117
+ for path in paths:
118
+ data=json.loads(path.read_text()); self.assertEqual(data["status"],"not-run",path)
119
+ self.assertTrue(data["preconditions"]); self.assertTrue(data["stop_conditions"])
120
+
121
+ if __name__ == "__main__": unittest.main()
@@ -0,0 +1,344 @@
1
+ """Actual offline helper tests. These do not execute an LLM or Istio."""
2
+ import ast
3
+ import json
4
+ import os
5
+ from pathlib import Path
6
+ import subprocess
7
+ import sys
8
+ import tempfile
9
+ import unittest
10
+
11
+ ROOT = Path(__file__).resolve().parents[2]
12
+ sys.path.insert(0, str(ROOT / "scripts"))
13
+ import istio_evidence_facts as f
14
+
15
+
16
+ def binding():
17
+ return {"cluster_id": "lab-id", "context": "lab", "namespace": "shop",
18
+ "resources": ["security.istio.io/AuthorizationPolicy/shop/restrict"],
19
+ "verbs": ["apply"], "baseline_sha256": "a" * 64,
20
+ "change_sha256": "b" * 64, "rollback_sha256": "c" * 64}
21
+
22
+
23
+ def approval():
24
+ return {"approval_id": "approval-1", "approver_ref": "external-identity-ref",
25
+ "review_ref": "review-1", "valid_from": "2026-09-08T10:00:00+04:00",
26
+ "valid_until": "2026-09-08T11:00:00+04:00", "binding": binding()}
27
+
28
+
29
+ class JsonInputTests(unittest.TestCase):
30
+ def test_valid(self):
31
+ self.assertEqual(f.parse_json(b'{"a":1}'), {"a": 1})
32
+
33
+ def test_duplicate_keys(self):
34
+ with self.assertRaises(f.InputError): f.parse_json(b'{"a":1,"a":2}')
35
+
36
+ def test_nonfinite(self):
37
+ for text in (b'NaN', b'Infinity', b'-Infinity'):
38
+ with self.subTest(text=text), self.assertRaises(f.InputError): f.parse_json(text)
39
+
40
+ def test_float_overflow_rejected(self):
41
+ with self.assertRaises(f.InputError): f.parse_json(b'1e9999')
42
+
43
+ def test_brackets_inside_string_do_not_count_as_nesting(self):
44
+ raw = json.dumps({"value": "[" * 100 + "\\\""}).encode()
45
+ self.assertEqual(len(f.parse_json(raw)["value"]), 102)
46
+
47
+ def test_explicit_depth_boundary(self):
48
+ self.assertIsInstance(f.parse_json(b'[' * 64 + b']' * 64), list)
49
+ with self.assertRaises(f.InputError): f.parse_json(b'[' * 65 + b']' * 65)
50
+
51
+ def test_invalid_utf8(self):
52
+ with self.assertRaises(f.InputError): f.parse_json(b'\xff')
53
+
54
+ def test_oversized(self):
55
+ with self.assertRaises(f.InputError): f.parse_json(b' ' * (f.MAX_INPUT_BYTES + 1))
56
+
57
+ def test_deep_input(self):
58
+ with self.assertRaises(f.InputError): f.parse_json(b'[' * 5000 + b']' * 5000)
59
+
60
+ def test_excessive_integer(self):
61
+ with self.assertRaises(f.InputError): f.parse_json(b'9' * 10000)
62
+
63
+ def test_invalid_syntax(self):
64
+ with self.assertRaises(f.InputError): f.parse_json(b'{"x":')
65
+
66
+
67
+ class RuleShapeTests(unittest.TestCase):
68
+ def test_absent_rules(self):
69
+ self.assertEqual(f.rule_list_shape({"action": "DENY"})["shape"], "absent")
70
+
71
+ def test_empty_list(self):
72
+ result = f.rule_list_shape({"action": "DENY", "rules": []})
73
+ self.assertEqual(result["shape"], "empty-list")
74
+ self.assertEqual(result["effective_access"], "not-evaluated")
75
+
76
+ def test_empty_rule_differs(self):
77
+ result = f.rule_list_shape({"action": "DENY", "rules": [{}]})
78
+ self.assertEqual(result["shape"], "contains-empty-rule")
79
+ self.assertEqual(result["empty_rule_count"], 1)
80
+
81
+ def test_constrained_rule(self):
82
+ self.assertEqual(f.rule_list_shape({"rules": [{"to": []}]})["shape"], "nonempty-constrained-rules")
83
+
84
+ def test_default_action(self):
85
+ self.assertEqual(f.rule_list_shape({})["action"], "ALLOW")
86
+
87
+ def test_bad_action(self):
88
+ for action in (None, "allow", "UNKNOWN", []):
89
+ with self.subTest(action=action), self.assertRaises(f.InputError): f.rule_list_shape({"action": action})
90
+
91
+ def test_null_and_scalar_rules(self):
92
+ for rules in (None, "", {}, [None], [1]):
93
+ with self.subTest(rules=rules), self.assertRaises(f.InputError): f.rule_list_shape({"rules": rules})
94
+
95
+
96
+ class WeightTests(unittest.TestCase):
97
+ def test_proportional_equivalence(self):
98
+ self.assertEqual(f.relative_weights([9, 1])["shares"], f.relative_weights([90, 10])["shares"])
99
+
100
+ def test_exact_fractions(self):
101
+ self.assertEqual(f.relative_weights([1, 2])["shares"], ["1/3", "2/3"])
102
+
103
+ def test_zero_component(self):
104
+ self.assertEqual(f.relative_weights([0, 10])["shares"], ["0", "1"])
105
+
106
+ def test_no_observation_claim(self):
107
+ result = f.relative_weights([9, 1])
108
+ self.assertEqual(result["observed_distribution"], "not-measured")
109
+ self.assertEqual(result["api_validation"], "not-performed")
110
+
111
+ def test_invalid_weights(self):
112
+ for weights in ([], [0, 0], [-1, 3], [True, 2], [0.2, 0.8], ["9", 1], None):
113
+ with self.subTest(weights=weights), self.assertRaises(f.InputError): f.relative_weights(weights)
114
+
115
+
116
+ class StatusTests(unittest.TestCase):
117
+ def result(self, generation, observed):
118
+ return f.condition_freshness(generation, {"type": "Accepted", "status": "True", "observedGeneration": observed})
119
+
120
+ def test_stale(self): self.assertEqual(self.result(2, 1)["generation_relation"], "stale")
121
+ def test_current(self): self.assertEqual(self.result(2, 2)["generation_relation"], "current")
122
+ def test_missing(self): self.assertEqual(self.result(2, None)["generation_relation"], "unknown")
123
+ def test_future(self): self.assertEqual(self.result(2, 3)["generation_relation"], "inconsistent-future-generation")
124
+
125
+ def test_current_is_not_traffic_proof(self):
126
+ self.assertEqual(self.result(2, 2)["end_to_end_behavior"], "not-proven")
127
+ self.assertEqual(self.result(2, 2)["parent_and_controller_ownership"], "not-checked")
128
+
129
+ def test_invalid_generation(self):
130
+ for generation in (0, -1, True, "2"):
131
+ with self.subTest(generation=generation), self.assertRaises(f.InputError): self.result(generation, 1)
132
+
133
+ def test_boolean_status_rejected(self):
134
+ with self.assertRaises(f.InputError): f.condition_freshness(2, {"type": "Accepted", "status": True})
135
+
136
+
137
+ class VersionTests(unittest.TestCase):
138
+ def test_direction(self):
139
+ self.assertEqual(f.directional_skew("1.30.0", "1.29.5")["numeric_relation"], "control-plane-one-minor-ahead")
140
+ self.assertEqual(f.directional_skew("1.29.5", "1.30.0")["numeric_relation"], "data-plane-minor-ahead")
141
+
142
+ def test_more_than_one_minor(self):
143
+ self.assertEqual(f.directional_skew("1.30.0", "1.28.0")["numeric_relation"], "control-plane-more-than-one-minor-ahead")
144
+
145
+ def test_patch(self):
146
+ self.assertEqual(f.directional_skew("1.30.0", "1.30.1")["numeric_relation"], "same-minor-data-plane-newer-patch")
147
+
148
+ def test_same_minor(self):
149
+ self.assertEqual(f.directional_skew("1.30.2", "1.30.1")["numeric_relation"], "same-minor")
150
+
151
+ def test_different_major(self):
152
+ self.assertEqual(f.directional_skew("2.0.0", "1.30.0")["numeric_relation"], "different-major-requires-specific-review")
153
+
154
+ def test_numeric_only_not_support(self):
155
+ self.assertEqual(f.directional_skew("1.20.0", "1.19.0")["support_status"], "not-determined")
156
+
157
+ def test_invalid_versions(self):
158
+ for version in ("latest", "1.30", "v1.30.0", "01.30.0", "1.30.0-rc.1", None):
159
+ with self.subTest(version=version), self.assertRaises(f.InputError): f.directional_skew(version, "1.30.0")
160
+
161
+
162
+ class StorageTests(unittest.TestCase):
163
+ def crd(self):
164
+ return {"spec": {"versions": [{"name": "v1", "storage": True, "served": True}, {"name": "v1beta1", "storage": False, "served": False}]}, "status": {"storedVersions": ["v1", "v1beta1"]}}
165
+
166
+ def test_historical_storage(self):
167
+ result = f.crd_storage_summary(self.crd())
168
+ self.assertEqual(result["storage_write_version"], "v1")
169
+ self.assertEqual(result["historical_versions_not_served"], ["v1beta1"])
170
+ self.assertEqual(result["stored_object_migration"], "not-proven")
171
+
172
+ def test_missing_history(self):
173
+ crd = self.crd(); del crd["status"]
174
+ self.assertIsNone(f.crd_storage_summary(crd)["historical_stored_versions"])
175
+
176
+ def test_multiple_storage(self):
177
+ crd = self.crd(); crd["spec"]["versions"][1]["storage"] = True
178
+ with self.assertRaises(f.InputError): f.crd_storage_summary(crd)
179
+
180
+ def test_no_storage(self):
181
+ crd = self.crd(); crd["spec"]["versions"][0]["storage"] = False
182
+ with self.assertRaises(f.InputError): f.crd_storage_summary(crd)
183
+
184
+ def test_duplicate_version(self):
185
+ crd = self.crd(); crd["spec"]["versions"][1]["name"] = "v1"
186
+ with self.assertRaises(f.InputError): f.crd_storage_summary(crd)
187
+
188
+
189
+ class RoutingTests(unittest.TestCase):
190
+ def test_minimal_owner(self):
191
+ self.assertEqual(f.route_review("review", ["authorization"])["review_owners"], ["istio-authorization-policy-review-agent"])
192
+
193
+ def test_ambient_precedes_authorization(self):
194
+ self.assertEqual(f.route_review("review", ["authorization", "ambient"])["review_owners"], ["istio-ambient-mesh-review-agent", "istio-authorization-policy-review-agent"])
195
+
196
+ def test_mutation_never_dispatches(self):
197
+ result = f.route_review("mutate", ["authorization"])
198
+ self.assertEqual(result["mode"], "live-guard-handoff")
199
+ self.assertEqual(result["auto_dispatch"], [])
200
+ self.assertEqual(result["handoff_owner"], "kubernetes-live-mesh-policy-guard-agent")
201
+
202
+ def test_collection_handoff(self):
203
+ self.assertEqual(f.route_review("collect", [])["mode"], "runtime-collection-handoff")
204
+
205
+ def test_empty_is_unresolved(self): self.assertEqual(f.route_review("review", [])["mode"], "needs-review")
206
+
207
+ def test_unknown_owner(self):
208
+ with self.assertRaises(f.InputError): f.route_review("review", ["imagined-owner"])
209
+
210
+ def test_duplicate_owner(self):
211
+ with self.assertRaises(f.InputError): f.route_review("review", ["ambient", "ambient"])
212
+
213
+ def test_unknown_blocks_approval(self):
214
+ result = f.aggregate_reviews([{"id": "a", "scope_id": "s", "verdict": "approved"}, {"id": "b", "scope_id": "s", "verdict": "needs-review"}])
215
+ self.assertEqual(result["verdict"], "needs-review")
216
+
217
+ def test_blocker_preserved(self):
218
+ result = f.aggregate_reviews([{"id": "a", "scope_id": "s", "verdict": "approved"}, {"id": "b", "scope_id": "s", "verdict": "blocked"}])
219
+ self.assertEqual(result["verdict"], "blocked")
220
+
221
+ def test_cross_scope_not_aggregated(self):
222
+ self.assertEqual(f.aggregate_reviews([{"id": "a", "scope_id": "s1", "verdict": "approved"}, {"id": "b", "scope_id": "s2", "verdict": "approved"}])["verdict"], "needs-review")
223
+
224
+ def test_approved_not_authorization(self):
225
+ result = f.aggregate_reviews([{"id": "a", "scope_id": "s", "verdict": "approved"}])
226
+ self.assertEqual(result["verdict"], "approved")
227
+ self.assertEqual(result["execution_authorization"], "not-granted")
228
+
229
+ def test_duplicate_reviews(self):
230
+ item = {"id": "a", "scope_id": "s", "verdict": "approved"}
231
+ with self.assertRaises(f.InputError): f.aggregate_reviews([item, item])
232
+
233
+ def test_empty_reviews(self):
234
+ with self.assertRaises(f.InputError): f.aggregate_reviews([])
235
+
236
+
237
+ class ApprovalBindingTests(unittest.TestCase):
238
+ def check(self, apr=None, current=None, as_of="2026-09-08T10:30:00+04:00"):
239
+ return f.approval_binding_check(apr or approval(), current or binding(), as_of)
240
+
241
+ def test_matching_not_authority(self):
242
+ result = self.check()
243
+ self.assertTrue(result["binding_matches"])
244
+ self.assertEqual(result["approval_authenticity"], "not-verified")
245
+ self.assertEqual(result["execution_authorization"], "not-granted")
246
+
247
+ def test_every_bound_field_detects_drift(self):
248
+ for key in f.BINDING_KEYS:
249
+ current = binding()
250
+ if key in ("resources", "verbs"):
251
+ current[key] = ["patch"] if key == "verbs" else ["security.istio.io/AuthorizationPolicy/shop/different"]
252
+ elif key.endswith("sha256"):
253
+ current[key] = "d" * 64
254
+ else:
255
+ current[key] = "different"
256
+ with self.subTest(field=key):
257
+ self.assertIn(key, self.check(current=current)["mismatches"])
258
+
259
+ def test_expiry_exclusive(self):
260
+ self.assertIn("validity_window", self.check(as_of="2026-09-08T11:00:00+04:00")["mismatches"])
261
+
262
+ def test_not_yet_valid(self):
263
+ self.assertIn("validity_window", self.check(as_of="2026-09-08T09:59:59+04:00")["mismatches"])
264
+
265
+ def test_start_inclusive(self):
266
+ self.assertTrue(self.check(as_of="2026-09-08T10:00:00+04:00")["binding_matches"])
267
+
268
+ def test_timezone_equivalence(self):
269
+ self.assertTrue(self.check(as_of="2026-09-08T06:30:00Z")["binding_matches"])
270
+
271
+ def test_naive_time_rejected(self):
272
+ with self.assertRaises(f.InputError): self.check(as_of="2026-09-08T10:30:00")
273
+
274
+ def test_reversed_window(self):
275
+ apr = approval(); apr["valid_until"] = apr["valid_from"]
276
+ with self.assertRaises(f.InputError): self.check(apr=apr)
277
+
278
+ def test_unknown_approval_field(self):
279
+ apr = approval(); apr["approved"] = True
280
+ with self.assertRaises(f.InputError): self.check(apr=apr)
281
+
282
+ def test_bad_digest(self):
283
+ current = binding(); current["change_sha256"] = "abc"
284
+ with self.assertRaises(f.InputError): self.check(current=current)
285
+
286
+ def test_unknown_verb(self):
287
+ current = binding(); current["verbs"] = ["force-delete-all"]
288
+ with self.assertRaises(f.InputError): self.check(current=current)
289
+
290
+ def test_wildcard_resource_is_rejected(self):
291
+ apr = approval(); apr["binding"]["resources"] = ["*"]
292
+ current = binding(); current["resources"] = ["*"]
293
+ with self.assertRaises(f.InputError): self.check(apr=apr, current=current)
294
+
295
+ def test_wildcard_resource_segment_is_rejected(self):
296
+ resource = "security.istio.io/AuthorizationPolicy/*/restrict"
297
+ apr = approval(); apr["binding"]["resources"] = [resource]
298
+ current = binding(); current["resources"] = [resource]
299
+ with self.assertRaises(f.InputError): self.check(apr=apr, current=current)
300
+
301
+
302
+ class CliTests(unittest.TestCase):
303
+ def run_cli(self, data, *args, env=None):
304
+ return subprocess.run([sys.executable, str(ROOT / "scripts/istio_evidence_facts.py"), *args], input=data, capture_output=True, env=env, timeout=10)
305
+
306
+ def test_stdin_success(self):
307
+ run = self.run_cli(b'{"operation":"relative-weights","input":{"weights":[9,1]}}')
308
+ self.assertEqual(run.returncode, 0)
309
+ self.assertEqual(json.loads(run.stdout)["shares"], ["9/10", "1/10"])
310
+
311
+ def test_failure_does_not_echo_secret(self):
312
+ run = self.run_cli(b'{"SECRET_TOKEN_ABC":')
313
+ self.assertEqual(run.returncode, 2)
314
+ self.assertNotIn(b'SECRET_TOKEN_ABC', run.stderr)
315
+ self.assertNotIn(b'Traceback', run.stderr)
316
+
317
+ def test_operation_extra_keys_rejected(self):
318
+ run = self.run_cli(b'{"operation":"relative-weights","input":{"weights":[1],"command":"unexpected"}}')
319
+ self.assertEqual(run.returncode, 2)
320
+
321
+ def test_symlink_file_rejected(self):
322
+ with tempfile.TemporaryDirectory() as tmp:
323
+ path = Path(tmp); (path / "real").write_text('{}'); (path / "alias").symlink_to(path / "real")
324
+ self.assertEqual(self.run_cli(b'', str(path / "alias")).returncode, 2)
325
+
326
+ def test_present_kubeconfig_ignored(self):
327
+ with tempfile.TemporaryDirectory() as tmp:
328
+ kube = Path(tmp) / "config"; kube.write_text('PRIVATE_CANARY')
329
+ env = {**os.environ, "KUBECONFIG": str(kube)}
330
+ run = self.run_cli(b'{"operation":"relative-weights","input":{"weights":[9,1]}}', env=env)
331
+ self.assertEqual(run.returncode, 0)
332
+ self.assertNotIn(b'PRIVATE_CANARY', run.stdout + run.stderr)
333
+ self.assertEqual(kube.read_text(), 'PRIVATE_CANARY')
334
+
335
+ def test_helper_has_no_network_shell_or_environment_import(self):
336
+ tree = ast.parse((ROOT / "scripts/istio_evidence_facts.py").read_text())
337
+ imports = []
338
+ for node in ast.walk(tree):
339
+ if isinstance(node, ast.Import): imports.extend(alias.name.split('.')[0] for alias in node.names)
340
+ if isinstance(node, ast.ImportFrom): imports.append((node.module or '').split('.')[0])
341
+ self.assertFalse(set(imports) & {"socket", "requests", "urllib", "http", "subprocess", "os", "kubernetes"})
342
+
343
+
344
+ if __name__ == '__main__': unittest.main()